絵文字が安全としてマークされる

運用している公開サイトで絵文字が壊れるのを目にしました。ACLはプライベートに設定されており、access control post dictates security | source: post creator という理由でセキュアとしてマークされています。

uploads:secure_upload_analyse_and_update タスクを実行すると問題は解決しますが、数日後に再び発生します。サイトのロゴでも一度同様のことが発生しましたが、その後は発生していません。

「いいね!」 3

@Wolftallemo さん、カスタム絵文字(または投稿で使用される可能性のある公開アップロード)とセキュアなアップロードが組み合わさると、これは少し厄介な問題になります。しばらく前に、アップロードが何にリンクされているかを確認するために UploadReference テーブルを使用し始めましたが、このテーブルに移行した際にすべての created_at日時を同じ値に設定しました。その結果、セキュリティ目的でアップロードの最初の使用が公開されているかどうかを確認する際に、順序がずれてしまい、間違ったものが使用されることがあります。もし両方の created_at が全く同じ場合、PostgreSQL は独自の処理を行います。

この件について言及していただいたことで、もう一度これを再検討しました。created_at ASC の後に id ASC で並べ替えることで、この問題をより良く対処できると思います。これにより、これらの競合が発生した場合でも、実際の最初のレコードが使用されるはずです。

これがマージされた後(本日中にマージできるよう努めます)も問題が続く場合、そしてサイトをアップロードされた場合は、さらにオプションを検討できますが、これがあなたの問題の原因であると疑っています。サイトでこの操作を実行し、結果を比較することで確認できます。

CustomEmoji.find_by(name: "success").upload.upload_references.order("created_at ASC")

CustomEmoji.find_by(name: "success").upload.upload_references.order("created_at ASC, id ASC")

最初のクエリでは Posttarget_type として表示され、2番目のクエリでは CustomEmojitarget_type として表示されるはずです。

「いいね!」 4

また発生し始めました。毎回同じ絵文字のようです。

「いいね!」 2

上記の投稿で@martinが共有したクエリを実行できますか?

「いいね!」 2

結果を見ると、実際には正反対の結果になっています(最初は CustomEmoji が返され、2番目は Post が返されます)。

「いいね!」 2

興味深いですね。それでは正しいものが返ってきます。リンクされたアップロードについて、security_last_changed_reasonsecurity_last_changed_at の値を投稿し、access_control_post_id が入力されているかどうかを確認していただけますか?最初の参照がカスタム絵文字である場合、そのアップロードをセキュアとしてマークすべきではありません。これも試してみてください。

Upload.find(ID)
  .upload_references
  .joins(<<~SQL)
    LEFT JOIN posts ON upload_references.target_type = 'Post' AND upload_references.target_id = posts.id
  SQL
  .where("posts.deleted_at IS NULL")
  .order("upload_references.created_at ASC, upload_references.id ASC")
  .first

そして、どのようなレコードが返されるか確認してください。

「いいね!」 1

アクセス制御 post はセキュリティを規定します | source: post creator というメッセージが Wed, 22 Mar 2023 09:13:10.341411000 UTC +00:00 の日付とともに表示されました。

これは、3年以上前に作成され、一度も編集されていないプライベートカテゴリの投稿に対するコントロールポストIDを返しました。

「いいね!」 2

興味深いですね。その投稿でカスタム絵文字は使用されていましたか? 上記のアップロード参照コードをそのアップロードIDで実行すると、何が返されますか? アップロードレコードでこれを実行し、結果を投稿していただけると参考になります。

UploadSecurity.new(upload).should_be_secure_with_reason
「いいね!」 1

その投稿で使用されていました

クエリは以下を返しました。

#<UploadReference:0x0000ffffa6846100
 id: 752,
 upload_id: 236,
 target_type: "Post",
 target_id: 37246,
 created_at: Mon, 25 Nov 2019 22:24:50.002473000 UTC +00:00,
 updated_at: Sun, 29 May 2022 08:13:24.844072000 UTC +00:00
>

target_id は、絵文字がまったく含まれていない投稿を指しています。

Upload security は [true, "access control post dictates security"] を返します。

「いいね!」 2

これは本当に予期せぬことです。これを実行すると、UploadReference を介して投稿にリンクされているすべてのアップロードを取得できるはずです。

UploadReference.where(
    target_type: "Post",
    target_id: 37246,
)

投稿に参照があるにもかかわらず、UIにアップロードが表示されない場合は、移行の問題があったのかもしれません。

IDを間違って入力していたことが判明しました :facepalm:

はい、絵文字が含まれていますが、親トピックは削除されました。

「いいね!」 1

ええ、問題ありません。では、正しいアップロードでこれを再度実行すると、どうなりますか?

UploadSecurity.new(upload).should_be_secure_with_reason

そして

upload
  .upload_references
  .joins(<<~SQL)
    LEFT JOIN posts ON upload_references.target_type = 'Post' AND upload_references.target_id = posts.id
  SQL
  .where("posts.deleted_at IS NULL")
  .order("upload_references.created_at ASC, upload_references.id ASC")
  .first

もし本当に必要なら、CustomEmojiUploadReferenceレコードのcreated_atの日時を、そのアップロードの他のUploadReferenceレコードのいずれかよりも前のものに設定することもできますが、それは本来必要ないはずです。

明確にすべきでした。アップロードIDは正しかったのですが、投稿IDが間違っていました(そのため、絵文字が含まれていない投稿になってしまいました。ここに貼り付けたものは正しかったのですが、見つけようとしているときに間違って入力してしまいました)。

他のすべてのコマンドは同じものを返します。

「いいね!」 1

もしそうであれば、日付に関して奇妙な点がある可能性があり、それは自動移行によって引き起こされた可能性があります。これを実行してください。

CustomEmoji.find_by(name: "success").upload.upload_references.order("created_at ASC, id ASC")

target_type: "CustomEmoji" を示す UploadReference レコードを見つけてから、以下を実行してください。

UploadReference.find(ID).update!(created_at: UploadReference.find(752).created_at - 1.day))

その後、問題のあるアップロードに対してこれを実行してください。

upload.update_secure_status

これで解決するはずです…これは主に、この移行以降の古いアップロードの問題だと思います。もう1つの方法として、カスタム絵文字を削除し、再アップロードしてから以下を実行することもできます。

Jobs.enqueue(:rebake_custom_emoji_posts, name: EMOJI_NAME)

日付の更新の方が簡単でしょう。この件でご迷惑をおかけしました!

「いいね!」 1

今のところ、絵文字はもう安全ではありません :meow_heart:

数日後に実際に機能したかどうか分かるでしょう。

「いいね!」 1

@Wolftallemo:slight_smile:

この件は解決しましたでしょうか?

まだ何も壊れていません

「いいね!」 1