SharePointVault ~/gotchas/lists ⌕ Search 404 pages, error messages, scripts…Ctrl K ★ Star
M↓ README.mdM↓ client-written-identity-needs-the-server-author.md
sharepoint-vault›gotchas›lists›client-written-identity-needs-the-server-author.mdhistoryedit on GitHub
● GOTCHAlists· 3 min read

An evidence record whose "who" is written by the browser proves nothing — compare it with the server-stamped Author, and compare on the sign-in name too

applies to: SharePoint Onlinereviewed: 2026-10-04#lists#permissions#audit#rest-api#security

If an audit list (confirmations, sign-offs, votes) stores the person in a text column the page fills in, anyone who may add rows can add one under a colleague's name — append-only permissions do not stop that. SharePoint stamps Author itself; compare the claimed name with it and do not count rows where they differ. Compare against Author/Name (the claim, which carries the UPN) as well as Author/EMail and Author/Title, otherwise every user whose e-mail is not their UPN is flagged on their genuine records.

Když auditní seznam (potvrzení, schválení, hlasy) drží člověka v textovém sloupci, který vyplní stránka, zapíše řádek pod cizím jménem každý, kdo smí přidávat – režim „jen přidávat" tomu nezabrání. Author razí SharePoint sám; porovnej s ním zapsané jméno a řádky, kde nesedí, nezapočítávej. Porovnávej i s Author/Name (claim s UPN), nejen s e-mailem a zobrazovaným jménem – jinak vyjde jako podvrh každý pravý záznam člověka, jehož e-mail není jeho UPN.

Symptom

A "who confirmed what" list runs with add-only permissions for every recipient. The page writes UserUpn = <current user> and the app counts confirmations per UserUpn. A user who knows the REST API posts a row with UserUpn = colleague@contoso.com, and the colleague now shows as compliant.

Cause

Every column in the POST body is the client's word. The system fields — Author, Created, Editor, Modified, _UIVersionString — are set by the server. Whether a given role can still write Author itself depends on its rights on the list (list-management rights are the ones to worry about); measure it for your roles with an account that holds them before you rely on the stamp.

Fix

  1. Read the author with the rows: $select=…,Author/Id,Author/Title,Author/EMail,Author/Name&$expand=Author.
  2. Treat a row as valid only if the claimed name matches the author on any of:
    • Author/Name after the last | (i:0#.f|membership|jan@contoso.onmicrosoft.com → the UPN; guests look like jan_gmail.com#ext#@contoso.onmicrosoft.com),
    • Author/EMail,
    • Author/Title, case-insensitive.
  3. Do not count non-matching rows, but do not hide them either — show them as "not counted, needs checking" in the UI and in exports. A rename can produce a legitimate mismatch.
  4. Rows you create on someone's behalf on purpose (sample data, an admin importing paper records) must carry their own marker (e.g. a method value) and be exempted explicitly.
  5. A row without author data is "unknown", not "forged" — never flip it either way.
const login = n => (n || '').substring((n || '').lastIndexOf('|') + 1).toLowerCase();
const norm = s => (s || '').trim().toLowerCase();
const matches = (claimed, a) => !!a && [login(a.Name), norm(a.EMail), norm(a.Title)].indexOf(norm(claimed)) !== -1;

Why the sign-in name matters (found in review before release)

The first version compared only with Author/Title and Author/EMail. The page wrote the user's e-mail when present and the UPN otherwise; in tenants where the e-mail is an alias or another domain, or for accounts without a mailbox, the genuine record never matched — a rule that "does not count mismatches" would have silently zeroed those people. Of the author fields used here, only Author/Name carries the UPN (in its claim); Title and EMail do not.

Notes

  • This is tamper-evidence, not tamper-proof: treat site owners and anyone with list-management rights as able to rewrite Author.
  • Aggregations over thousands of rows need only Author/*, not the full stamp set — keep the payload small.
Was this helpful?ask or add your experience on GitHub →
Saved you an hour? A star on GitHub helps other SharePoint people find the vault.★ Star on GitHub
last reviewed: 2026-10-04last updated: 2026-10-04historyedit on GitHubview source