{"record":{"id":"c16da74438704fe2","repo":"facebook/react","slug":"only-objects-or-functions-can-be-passed-to-taintob","errorCode":null,"errorMessage":"Only objects or functions can be passed to taintObjectReference. Try taintUniqueValue instead.","messagePattern":"Only objects or functions can be passed to taintObjectReference\\. Try taintUniqueValue instead\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react/src/ReactTaint.js","lineNumber":127,"sourceCode":"  } else {\n    existingEntry.count++;\n  }\n  if (finalizationRegistry !== null) {\n    finalizationRegistry.register(lifetime, entryValue);\n  }\n}\n\nexport function taintObjectReference(\n  message: ?string,\n  object: Reference,\n): void {\n  if (!enableTaint) {\n    throw new Error('Not implemented.');\n  }\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  message = '' + (message || defaultMessage);\n  if (typeof object === 'string' || typeof object === 'bigint') {\n    throw new Error(\n      'Only objects or functions can be passed to taintObjectReference. Try taintUniqueValue instead.',\n    );\n  }\n  if (\n    // $FlowFixMe[invalid-compare]\n    object === null ||\n    (typeof object !== 'object' && typeof object !== 'function')\n  ) {\n    throw new Error(\n      'Only objects or functions can be passed to taintObjectReference.',\n    );\n  }\n  TaintRegistryObjects.set(object, message);\n}\n","sourceCodeStart":109,"sourceCodeEnd":142,"githubUrl":"https://github.com/facebook/react/blob/eafeac097ba51e1eab809c07102126bd5f8e5425/packages/react/src/ReactTaint.js#L109-L142","documentation":"taintObjectReference registers identity-based taints via a WeakMap and only accepts objects or functions. Strings and bigints are value types with no stable identity, so passing one throws early with a hint to use taintUniqueValue, which is the registry built for unique scalar values.","triggerScenarios":"Calling taintObjectReference(message, 'some-secret-string') or taintObjectReference(message, 123n) — passing a string/bigint where the object argument goes.","commonSituations":"Argument-order confusion between the two taint APIs (message first, then value); upgrading security review fixes that swapped the intended API for secrets stored as strings.","solutions":["Use taintUniqueValue(message, lifetimeObject, secretString) for strings and bigints","Keep taintObjectReference for object/function references only","Double-check parameter order: message, then the tainted thing (plus lifetime for taintUniqueValue)"],"exampleFix":"// before\ntaintObjectReference(msg, apiKey); // apiKey is a string -> throws\n\n// after\ntaintUniqueValue(msg, requestContext, apiKey);","handlingStrategy":"type-guard","validationCode":"// Route strings/bigints to taintUniqueValue\nfunction taintValue(message: string, lifetime: object, value: unknown) {\n  if (typeof value === 'string' || typeof value === 'bigint') {\n    taintUniqueValue(message, lifetime, value);\n  } else {\n    taintObjectReference(message, value);\n  }\n}","typeGuard":"const isScalarSecret = (v: unknown): v is string | bigint =>\n  typeof v === 'string' || typeof v === 'bigint';","tryCatchPattern":null,"preventionTips":["Keep a cheat sheet: taintObjectReference(message, objOrFn) vs taintUniqueValue(message, lifetime, string|bigint|binary)","Parameter order differs between the two APIs — review calls carefully when hardening secrets"],"tags":["security","taint-apis","taintobjectreference","wrong-api"],"backgroundTag":"taint-api-misuse","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}