Discourse rileva erroneamente il file caricato come immagine

Ho alcuni utenti di ingegneria che desiderano allegare alcuni file di dati con estensioni di file non comuni ai loro post. Sono essenzialmente file di testo normale ma includono caratteri ASCII estesi.

Ho provato ad aggiornare la configurazione NGINX di Discourse per specificare i tipi MIME per questi file, ma non ha funzionato. Ho pubblicato un argomento (How to customize MIME media type emitted for certain attachments?) su questo due settimane fa ma non ho ancora ricevuto risposte. Anche se NGINX non viene aggiornato, servirà comunque tipi di file sconosciuti utilizzando il tipo MIME di fallback “application/octet-stream”. Posso conviverci per ora.

Tuttavia, quando gli utenti tentano di caricare questi file di dati in un post (utilizzando il pulsante “Carica” o trascinando e rilasciando), ricevono un popup di errore da Discourse simile a questo:

Sembra che quando gli utenti caricano file, Discourse stia cercando di essere intelligente e di rilevare se si tratta di un’immagine o di un altro tipo di file. Inoltre, sembra che stia facendo questa determinazione esaminando il contenuto del file (molto simile al comando standard Unix “file”). Presumo che questo sia in modo che Discourse possa decidere se incorporarlo nel contenuto del post o metterlo da parte come allegato.

Nel caso di questi file di dati, questo controllo sta identificando erroneamente i file come immagini. Solo per divertimento, ho messo alcuni di questi file di dati su una macchina Ubuntu e li ho controllati con il comando “file”, e in effetti, sono stati identificati come “dati immagine JPEG”.

C’è un modo per gli utenti di caricare file senza che Discourse cerchi di rilevare se sono immagini? Cioè, “Per favore, carica questo come allegato, non importa cosa, non incorporarlo”?

In alternativa, potrei configurare Discourse per consentire i file zip e dire agli utenti di comprimere i loro file prima di caricarli, ma preferirei non aprire il sito a caricamenti casuali di file zip. Sembra un problema di sicurezza.

Grazie in anticipo per qualsiasi aiuto!

Un’altra soluzione è adottare un’estensione per quei file strani, come .bin, .data o davvero .anythinggoes, che dovrebbe essere sufficiente affinché Discourse li ignori.

Grazie per la rapida risposta! Tuttavia, ho provato e non funziona. Discourse sta sicuramente guardando il contenuto del file, non l’estensione, per determinare se si tratta di un’immagine o meno.

1 Mi Piace

Qualcuno ha qualche pensiero a riguardo? Sembra un bug piuttosto significativo.

Ho fatto qualche ricerca su questo problema.

In breve, il tuo file viene rilevato come JPEG perchĂŠ inizia con la stessa firma di questo tipo di file.
È possibile correggere questo comportamento in Discourse, ma richiede una modifica. (vedi alla fine)


Ecco alcune informazioni tecniche.
Questo problema inizia qui:

La libreria FastImage apre il file e ne determina il tipo e le dimensioni.
Come previsto, restituisce un tipo JPEG.

Se guardi la firma JPEG, appare cosĂŹ:

Marcatori JPEG

Maggiori informazioni: List of file signatures - Wikipedia
JPEG - Wikipedia

Inizia sempre con i seguenti byte di marcatore: FF D8

Guardando il tuo campione di file con un editor esadecimale, vedrai che inizia allo stesso modo.

Ora, se guardi come FastImage rileva un JPEG, puoi vedere qui:

Tuttavia, non è possibile estrarre alcuna informazione sull’immagine poiché non sono presenti tutti i byte richiesti.

Come risolviamo questo problema in Discourse?
Guardando il codice di FastImage, c’è un’opzione preziosa che puoi passare.

Utilizzando questa opzione, qualsiasi errore (SizeNotFound, ImageFetchFailure, CannotParseImage, UnknownImageType, BadImageURI) restituirà nessuna informazione sull’immagine; e il tuo file non verrà rilevato come immagine.

@image_info =
  begin
    FastImage.new(@file, raise_on_failure: true)
  rescue StandardError
    nil
  end
...
is_image ||= @image_info && FileHelper.is_supported_image?("test.#{@image_info.type}")

Quindi, ora può funzionare:

Posso fare una PR più tardi. L’uso di questa opzione ha senso qui. :+1:

2 Mi Piace

Wow! Questa è un’analisi fenomenale! Grazie!

Alcune domande rapide:

  1. Quindi, con queste modifiche, il file non verrĂ  rilevato come immagine e verrĂ  caricato come non immagine e visualizzato a destra del post?

  2. Se ho capito bene, mi stai suggerendo di apportare queste modifiche nella mia istanza locale di Discourse per provarle e/o usarle finchĂŠ non saranno incluse in una futura versione di Discourse. Ma come faccio? (Sono uno sviluppatore software esperto ma ho esperienza limitata con Docker e nessuna con Ruby.)

  3. La chiamata FastImage che dovrebbe essere modificata è in models/upload.rb, giusto?

  1. SÏ, è corretto, come nello screenshot qui sopra

  2. Non sto suggerendo di apportare la modifica. Tuttavia, se non puoi aspettare, potresti certamente testare quella modifica.

  • Per una modifica temporanea (scomparirĂ  dopo la ricostruzione):
cd /var/discourse
./launcher enter app
sed -i "s/FastImage.new(@file)/FastImage.new(@file, :raise_on_failure=true)/" lib/upload_creator.rb
sed -i "s/FastImage.new(original_path)/FastImage.new(original_path, :raise_on_failure=true)/" app/models/upload.rb
exit
  • Per una modifica persistente (rimarrĂ  dopo la ricostruzione):
cd /var/discourse
nano containers/app.yml  (usa il tuo editor preferito)

Aggiungi i seguenti comandi personalizzati alla fine (sezione run):

  - replace:
      filename: "/var/www/discourse/lib/upload_creator.rb"
      from: "FastImage.new(@file)"
      to: "FastImage.new(@file, :raise_on_failure=true)"
  - replace:
      filename: "/var/www/discourse/app/models/upload.rb"
      from: "FastImage.new(original_path)"
      to: "FastImage.new(original_path, :raise_on_failure=true)"

Quindi, ricostruisci:

./launcher rebuild app
  1. Immagino di sĂŹ se hai intenzione di caricare file senza estensioni. Non ho controllato se altre occorrenze richiedessero la stessa modifica.
1 Mi Piace

@Arkshine – Grazie mille per questi dettagli. Sono riuscito a testare entrambe le correzioni separatamente (ognuna su una VM ripristinata di fresco) e hanno funzionato entrambe!

Note:

  1. Per la correzione temporanea, ho dovuto eseguire “launcher restart app” affinché le modifiche avessero effetto.

  2. Sembra che anche “spec/models/optimized_image_spec.rb” abbia un riferimento a FastImage.new(). Deve essere aggiornato anche questo come gli altri?

Grazie ancora per il tuo aiuto!

Sono contento che funzioni. :slight_smile:

  1. Questo è solo a scopo di test, quindi non devi preoccupartene.

Ottimo! Grazie! Ora che l’ho testato nel mio ambiente di sviluppo, lo distribuiremo negli ambienti di test e di produzione.

A proposito, se hai tempo, mi piacerebbe avere la tua opinione su un problema correlato (How to customize MIME media type emitted for certain attachments?).

1 Mi Piace

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.