PUT page preserves user-supplied `creator` on existing-line updates
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
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.generatedByis intact (RERUM stamps that from auth), so the underlying "who actually wrote this version" is recoverable. - The body-level
creatoris 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/hasSuspiciousPageDatadon't normalizecreator; 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from CenterForDigitalHumanities/TPEN-services
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
CenterForDigitalHumanities/TPEN-services#525 · 3 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
core-functionality enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
CenterForDigitalHumanities/TPEN-services#532 · 1 comment · 2 reactions · 2 assignees ·
-
CenterForDigitalHumanities/TPEN-services#521 · 1 reaction · 2 assignees ·
All issues in CenterForDigitalHumanities/TPEN-services
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
HarperFast/skills#96 ·
-
[Block] Latest Posts [Type] Bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Automattic/studio#4908 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
sugarlabs/musicblocks#8847 ·