Problem/Motivation

An image field with a maximum resolution scales a larger upload while it is being uploaded, and the stored file has no C2PA manifest any more, so the module makes no suggestion and logs nothing (#3631521: Known issue: an image field with a maximum resolution removes the content credential, a known issue in 1.0.0-alpha1). A maximum resolution is ordinary site configuration.

Core scales inside the FileImageDimensions constraint validator, which runs on the uploaded temporary file before it is moved and saved. There is no hook or event between validation and scaling.

Proposed resolution

Replace that constraint's class, only while it is still core's own, with a subclass whose validator copies a signed upload that is about to be scaled to temporary://content_credentials/ and then lets core scale it as before. The queue worker reads the copy instead of the stored file, the suggestion's note says it was read from the upload before Drupal scaled it, and the copy is removed afterwards. Nothing is parsed in the save request: it only searches the bytes for the manifest store's identifier and copies the file.

Measured before deciding: the replacement works through the node form on Drupal 11.3.19 and 11.4.10, and the copy keeps the manifest byte for byte. The search found every embedded manifest in a corpus of 983 files, and copy plus search took about 8 ms for a 15.5 MiB file, against about 105 ms for core's own scaling of it.

The module then depends on a core class that is not an API promise. If core renames it, uploads behave as they do today; tests on the current and previous minor guard the rest.

Remaining tasks

  • [ ] Fix with tests (SPEC 033)
  • [ ] Remove the known issue from the CHANGELOG in the release that ships it

Comments

maurice1969 created an issue. See original summary.

  • maurice1969 committed 79f55a13 on 1.0.x
    Issue #3631631 by maurice1969: SPEC 033 — keep the original of an upload...

  • maurice1969 committed 79f55a13 on main
    Issue #3631631 by maurice1969: SPEC 033 — keep the original of an upload...

  • maurice1969 committed 788da84d on 1.0.x
    Issue #3631631 by maurice1969: SPEC 033 Amendment 1 — kept copies are...

  • maurice1969 committed 788da84d on main
    Issue #3631631 by maurice1969: SPEC 033 Amendment 1 — kept copies are...
maurice1969’s picture

Status: Active » Fixed

Fixed in 79f55a1, with a follow-up from a security review of that commit in 788da84: a copy now goes with its file, a copy that no read reaches is removed after 24 hours, and copies are readable by the web server's user only. Neither commit is in a release yet; 1.0.0-alpha1 still has the known issue in #3631521.

Tested on Drupal 11.3.19 and 11.4.10, and CI passed on every job.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

maurice1969’s picture

Status: Fixed » Active

Reopening for two follow-ups found in a review before the alpha2 tag, both measured:

  • A kept copy is removed 24 hours after the upload, while a read waiting for an unreachable reading service (#3631662: Keep a queued read while the reading service is unreachable, for up to a day) may wait until 24 hours after the content was saved, which can be up to six hours later. Cron removes copies before it runs the queue, so an outage that ends in that gap reads the scaled file and makes no suggestion. Kept copies will be removed after 30 hours instead.
  • Code that replaces a file in place keeps its file ID. When the new bytes are not kept, the previous upload's copy is still read, and the suggestion describes a file the page no longer shows. Core's own upload paths always rename, so this needs contrib or custom code. The copy will be read only while the stored file is the one it was kept for, checked by a hash taken when the copy is claimed.

  • maurice1969 committed cfac0331 on 1.0.x
    Issue #3631631, #3631662 by maurice1969: README and CHANGELOG — scaled...

  • maurice1969 committed 75c18031 on 1.0.x
    Issue #3631631 by maurice1969: SPEC 033 Amendment 2 — the copy outlives...

  • maurice1969 committed cfac0331 on main
    Issue #3631631, #3631662 by maurice1969: README and CHANGELOG — scaled...

  • maurice1969 committed 75c18031 on main
    Issue #3631631 by maurice1969: SPEC 033 Amendment 2 — the copy outlives...
maurice1969’s picture

Status: Active » Fixed

Both follow-ups are committed to 1.0.x as 75c1803, with the README and CHANGELOG in cfac033; CI green. Claimed copies now last 31 hours: the 24-hour window for a waiting read, the six hours an upload may wait before its content is saved, and the hour a read may be set aside for. A copy is read only while the stored file still matches the SHA-256 taken when the copy was claimed; otherwise the stored file is read and a notice says so. It will be in 1.0.0-alpha2.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.