PUT page preserves user-supplied `creator` on existing-line updates

Open Beginner friendly
#500 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
74/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
javascript
Domain
api, backend, security

Research direction

Start at the page PUT route in page/index.js:119-123, then read the Line constructor and build method in classes/Line/Line.js:16-36. Check how fetchUserAgent in utilities/shared.js:343-358 handles the existing-line update. Done means an input-supplied creator cannot replace the authenticated user's agent on the saved line.

Written by the indexing model from the issue text.

Description

Summary

The page PUT route lets a client override creator on an existing-line update. Authenticated callers can attribute a saved line to any agent IRI they choose. New lines are unaffected.

Where

page/index.js:119-123

const line = item.id?.startsWith?.('http')
    ? new Line(item)
    : Line.build(projectId, pageId, item, user.agent.split('/').pop())
line.creator ??= user.agent.split('/').pop()

For the http-id branch, new Line(item) reads creator from input via destructuring (classes/Line/Line.js:16-29). The ??= on the next line only fills when nullish, so an input-supplied creator is preserved. The Line.build branch is safe — its destructure (Line.js:32-36) drops creator from input and uses the function-arg from user.agent.

#saveLineToRerum then writes the line to RERUM via creator: await fetchUserAgent(this.creator). fetchUserAgent (utilities/shared.js:343-358) returns any string starting with http verbatim, so the supplied IRI flows through unchanged.

Reproduction

PUT a page with an existing-line update whose body carries a fake creator:

PUT /project/{projectId}/page/{pageId}
Authorization: Bearer <legitimate user token>
Content-Type: application/json

{
  "items": [
    {
      "id": "https://store.rerum.io/v1/id/<existing-line-id>",
      "body": [{ "type": "TextualBody", "value": "x", "format": "text/plain" }],
      "target": { /* unchanged */ },
      "creator": "https://store.rerum.io/v1/id/SOMEONE_ELSE"
    }
  ]
}

Returns 200. The new RERUM version of that line records creator: https://store.rerum.io/v1/id/SOMEONE_ELSE, not the authenticated user's agent.

Impact

  • Audit/provenance via __rerum.generatedBy is intact (RERUM stamps that from auth), so the underlying "who actually wrote this version" is recoverable.
  • The body-level creator is what consumers read for attribution display ("authored by X"). Anything that surfaces creator in the UI shows the wrong agent.
  • Authentication is required, so this isn't anonymous spoofing — but a token holder can attribute lines to other users, which has obvious abuse and audit-trail implications.
  • screenContentMiddleware / hasSuspiciousPageData don't normalize creator; the common_keys list checks for script injection in label/value/text/etc., not identity fields.

Suggested fix

Strip creator from input on the existing-line branch and force it from auth, mirroring how the page-level creator is set at page/index.js:95:

const line = item.id?.startsWith?.('http')
    ? new Line({ ...item, creator: undefined })
    : Line.build(projectId, pageId, item, user.agent.split('/').pop())
line.creator = user.agent.split('/').pop()

(Or hard-assign instead of ??= and document that creator is server-controlled, then strip in the constructor as a defense-in-depth.)

Worth a similar audit on the PUT /line/:lineId and PATCH routes — Object.assign(line, req.body) at line/index.js:130 has the same shape and likely the same exposure.

Found via

/static-review of TPEN-Prompts#4. The prompts UI accepts JSON pasted from an LLM and submits it via this PUT; an LLM that hallucinates a creator field would silently misattribute lines. The right defense is here, not in the client.

Dominant language
JavaScript
Stars
2
Forks
0
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from CenterForDigitalHumanities/TPEN-services

All issues in CenterForDigitalHumanities/TPEN-services

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.