[{"data":1,"prerenderedAt":1438},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Flimitations":135,"\u002Fdocs\u002Flimitations-surround":1433},[4],{"title":5,"path":6,"stem":7,"children":8,"page":134},"Docs","\u002Fdocs","docs",[9,13,17,21,25,29,33,37,41,45,49,53,57,61,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126,130],{"title":10,"path":11,"stem":12},"AI harnesses: LLM tools, MCP servers and agents","\u002Fdocs\u002Fai-tools","docs\u002Fai-tools",{"title":14,"path":15,"stem":16},"Architecture","\u002Fdocs\u002Farchitecture","docs\u002Farchitecture",{"title":18,"path":19,"stem":20},"Web \u002F native bridges","\u002Fdocs\u002Fbridges","docs\u002Fbridges",{"title":22,"path":23,"stem":24},"Broadcast channels and tests","\u002Fdocs\u002Fchannels-and-tests","docs\u002Fchannels-and-tests",{"title":26,"path":27,"stem":28},"CLI reference","\u002Fdocs\u002Fcli","docs\u002Fcli",{"title":30,"path":31,"stem":32},"Completeness: how far an answer reaches","\u002Fdocs\u002Fcompleteness","docs\u002Fcompleteness",{"title":34,"path":35,"stem":36},"Configuration","\u002Fdocs\u002Fconfiguration","docs\u002Fconfiguration",{"title":38,"path":39,"stem":40},"External systems","\u002Fdocs\u002Fexternal","docs\u002Fexternal",{"title":42,"path":43,"stem":44},"Generated, copied and vendored files","\u002Fdocs\u002Fgenerated","docs\u002Fgenerated",{"title":46,"path":47,"stem":48},"Installing and updating cg","\u002Fdocs\u002Finstall","docs\u002Finstall",{"title":50,"path":51,"stem":52},"Java","\u002Fdocs\u002Fjava","docs\u002Fjava",{"title":54,"path":55,"stem":56},"Kotlin","\u002Fdocs\u002Fkotlin","docs\u002Fkotlin",{"title":58,"path":59,"stem":60},"Known limitations","\u002Fdocs\u002Flimitations","docs\u002Flimitations",{"title":62,"path":63,"stem":64,"children":65},"MCP server","\u002Fdocs\u002Fmcp","docs\u002Fmcp",[66],{"title":67,"path":68,"stem":69},"code-graph MCP: sample outputs (real calls via the MCP Python SDK stdio client)","\u002Fdocs\u002Fmcp\u002Fsample_outputs","docs\u002Fmcp\u002Fsample_outputs",{"title":71,"path":72,"stem":73},"Rust, C and C++","\u002Fdocs\u002Fnative","docs\u002Fnative",{"title":75,"path":76,"stem":77},"Port gaps: cg parity","\u002Fdocs\u002Fparity","docs\u002Fparity",{"title":79,"path":80,"stem":81},"PHP","\u002Fdocs\u002Fphp","docs\u002Fphp",{"title":83,"path":84,"stem":85},"Planned changes","\u002Fdocs\u002Fplans","docs\u002Fplans",{"title":87,"path":88,"stem":89},"Platform-specific code","\u002Fdocs\u002Fplatforms","docs\u002Fplatforms",{"title":91,"path":92,"stem":93},"Protocol links","\u002Fdocs\u002Fprotocols","docs\u002Fprotocols",{"title":95,"path":96,"stem":97},"Python","\u002Fdocs\u002Fpython","docs\u002Fpython",{"title":99,"path":100,"stem":101},"Quick start","\u002Fdocs\u002Fquickstart","docs\u002Fquickstart",{"title":103,"path":104,"stem":105},"Graph schema","\u002Fdocs\u002Fschema","docs\u002Fschema",{"title":107,"path":108,"stem":109},"Attack surface","\u002Fdocs\u002Fsurface","docs\u002Fsurface",{"title":111,"path":112,"stem":113},"Swift","\u002Fdocs\u002Fswift","docs\u002Fswift",{"title":115,"path":116,"stem":117},"TypeScript \u002F JavaScript frameworks","\u002Fdocs\u002Fts-frameworks","docs\u002Fts-frameworks",{"title":119,"path":120,"stem":121},"How we validate","\u002Fdocs\u002Fvalidation","docs\u002Fvalidation",{"title":123,"path":124,"stem":125},"Validation log","\u002Fdocs\u002Fvalidation-log","docs\u002Fvalidation-log",{"title":127,"path":128,"stem":129},"Value facts and resolutions","\u002Fdocs\u002Fvalue-facts","docs\u002Fvalue-facts",{"title":131,"path":132,"stem":133},"Visual view","\u002Fdocs\u002Fviz","docs\u002Fviz",false,{"id":136,"title":58,"body":137,"description":143,"extension":1428,"meta":1429,"navigation":1430,"path":59,"seo":1431,"stem":60,"__hash__":1432},"docs\u002Fdocs\u002Flimitations.md",{"type":138,"value":139,"toc":1415},"minimark",[140,144,149,191,195,204,228,232,235,315,319,435,438,864,867,1174,1178,1294,1298],[141,142,143],"p",{},"code-graph is beta. This page is the cross-cutting ceiling: how far an answer reaches when the graph is incomplete.\nLanguage gaps are on the language pages, linked at the end.",[145,146,148],"h2",{"id":147},"types-and-dispatch","Types and dispatch",[150,151,152,156,164,171,174,177,188],"ul",{},[153,154,155],"li",{},"Types are flow-insensitive: one type set per variable per function. PHP generics are outside the current scope.",[153,157,158,159,163],{},"An unresolvable receiver falls back to a unique method name (",[160,161,162],"code",{},"heuristic",", with a stoplist).",[153,165,166,167,170],{},"A Builder passed as a generic ",[160,168,169],{},"Builder"," parameter loses its model.",[153,172,173],{},"A trait, interface, generic, or virtual call reaches every implementation or override in the graph.",[153,175,176],{},"The walk narrows to the receiver's class only where that type is known: the TypeScript checker, a Python inferred instance, or a Kotlin \u002F Swift \u002F Dart \u002F PHP typed value.",[153,178,179,180,183,184,187],{},"Generic substitution such as ",[160,181,182],{},"Repo[B]().get()"," returning ",[160,185,186],{},"T"," stays unresolved.",[153,189,190],{},"A callback passed as a JSX attribute is a reference from the JSX site. It stays unlinked from the component's prop, so a shared component does not become a hub of every call site.",[145,192,194],{"id":193},"gate-scenarios","Gate scenarios",[141,196,197,198,203],{},"One scenario per index (",[199,200,202],"a",{"href":201},"\u002Fdocs\u002Fconfiguration#gate-scenarios","gate scenarios",").",[150,205,206,209,216,219,222,225],{},[153,207,208],{},"The analysis is per function and context-insensitive. Parameters are TOP, except literal-argument method summaries.",[153,210,211,212,215],{},"A flag passed as data, or stored on a property (",[160,213,214],{},"$this->x","), stays live. That is the conservative choice.",[153,217,218],{},"The same canonical expression is the same atom. Bare null or empty checks assume the inputs are present.",[153,220,221],{},"A branch with more than 12 atoms is assumed feasible.",[153,223,224],{},"Middleware that aborts when a flag is off is not a gate.",[153,226,227],{},"An edge is gated only when the gated function itself makes the reference.",[145,229,231],{"id":230},"runtime-behaviour","Runtime behaviour",[141,233,234],{},"cg describes the indexed code. It does not model what a process does at run time. An empty answer is not \"this never happens\".",[150,236,237,254,284,309],{},[153,238,239,240,243,244,248,249,253],{},"Exception propagation and the HTTP status an exception becomes are out of scope. The graph has no throw \u002F catch edges. Whether an uncaught exception is a 500, a logged warning or a retry depends on the framework handler and the environment. The static substitute is the route and its guards: ",[160,241,242],{},"cg routes"," and ",[199,245,247],{"href":246},"\u002Fdocs\u002Fphp#inline-guards","inline guards",". Framework error bodies (validation 422, auth 401, 500 pages) stay absent; see ",[199,250,252],{"href":251},"#link-payload-and-guards","Link, payload, and guards",".",[153,255,256,257,260,261,264,265,268,269,243,272,275,276,279,280,253],{},"Whether a scheduler, a queue worker or cron is running is out of scope. Scheduled and queued work is only what the code declares (",[160,258,259],{},"schedule"," nodes, entry kind ",[160,262,263],{},"scheduled"," or ",[160,266,267],{},"queue_job","). ",[160,270,271],{},"cg writers",[160,273,274],{},"cg reaches"," list ",[160,277,278],{},"entries:"," on each writer. See ",[199,281,283],{"href":282},"\u002Fdocs\u002Fcli#readers-and-writers-specs","Readers and writers specs",[153,285,286,287,290,291,294,295,243,298,301,302,305,306,203],{},"Environment-specific config values are out of scope. cg reads declared keys and defaults (",[160,288,289],{},".env.example",", ",[160,292,293],{},"env()"," defaults), not the values a deploy injects. ",[160,296,297],{},"cg downstream",[160,299,300],{},"config:"," \u002F ",[160,303,304],{},"env:"," specs are the static substitute (",[199,307,308],{"href":35},"configuration",[153,310,311,312,253],{},"Data-dependent branches beyond the indexed gate scenario are out of scope. One scenario per index decides which edges are dead; a value that arrives only at run time stays live. See ",[199,313,194],{"href":314},"#gate-scenarios",[145,316,318],{"id":317},"index-and-answers","Index and answers",[150,320,321,331,344,358,365,372,375,386,411,414,417],{},[153,322,323,324,327,328,330],{},"A missing toolchain degrades that language: ",[160,325,326],{},"skipped",", or ",[160,329,162],{}," when the exact indexer is absent. The rest of the index still runs.",[153,332,333,336,337,340,341,203],{},[160,334,335],{},"cg coverage"," and the MCP ",[160,338,339],{},"coverage"," tool print the mode, the reason, and an install hint (",[199,342,343],{"href":31},"Completeness",[153,345,346,347,290,350,353,354,357],{},"Route lists, caller lists, ",[160,348,349],{},"reaches",[160,351,352],{},"tests",", and plan checks add a ",[160,355,356],{},"coverage note:"," when a blind spot or an unindexed file in the answer's languages and directories could affect them.",[153,359,360,361,364],{},"Empty replies and unknown symbols end with a coverage line. MCP replies carry a ",[160,362,363],{},"completeness"," object.",[153,366,367,368,253],{},"Blind-spot detectors are the list in ",[199,369,371],{"href":370},"\u002Fdocs\u002Fcompleteness#blind-spots","blind spots",[153,373,374],{},"Code generated at build or run time, and files outside the indexed root, are absent from the graph and from that list.",[153,376,377,378,381,382,385],{},"Generated or copied files need a marker from ",[199,379,380],{"href":43},"Generated files",": gitattributes, a banner, or a known build path. A generator with none of those is source until ",[160,383,384],{},"generated.paths"," names it.",[153,387,388,389,392,393,396,397,400,401,403,404,301,407,410],{},"A database connection chosen at run time from data (",[160,390,391],{},"Book::on($tenant->connection)",", a name read from a request or a property set in a constructor from an unknown source) is ",[160,394,395],{},"?"," on the table and column edges; ",[160,398,399],{},"--connection ?"," lists them. A name built from a parameter or a local is ",[160,402,395],{}," too. Read \u002F write replicas (",[160,405,406],{},"read",[160,408,409],{},"write"," hosts inside one connection) are one connection.",[153,412,413],{},"Dangling symlinks are skipped with a per-file warning. The TypeScript walker does not follow symlinked directories.",[153,415,416],{},"References taken from a SCIP index are attributed to the nearest enclosing definition by source range.",[153,418,419,420,423,424,427,428,430,431,434],{},"Go is a SCIP recipe (",[160,421,422],{},"plugins\u002Fstubs","), not a language plugin. Without a SCIP index its files are ",[160,425,426],{},"unsupported",". Java is a language plugin (",[199,429,50],{"href":51},"): heuristic by default, exact with scip-java when ",[160,432,433],{},"CG_JAVA_SCIP=1"," (one run shared with Kotlin). Spring facts are extracted with Kotlin from the shared JVM module.",[145,436,252],{"id":437},"link-payload-and-guards",[150,439,440,451,456,502,526,552,601,639,681,684,698,708,782,792,819,833,842,845],{},[153,441,442,445,446,450],{},[160,443,444],{},"cg link"," matches method and path (",[199,447,449],{"href":448},"\u002Fdocs\u002Farchitecture#cross-repo-link","cross-repo link","). Nest DTO fields and Fastify schema fields are stored and are not compared. Laravel FormRequest and inline validation keys, Elysia body schemas, and client body or query keys are compared when the route has a request schema.",[153,452,453,454,253],{},"An endpoint whose origin was not traced matches by suffix at ",[160,455,162],{},[153,457,458,459,301,462,301,465,468,469,243,472,475,476,479,480,290,483,485,486,488,489,491,492,495,496,499,500,203],{},"PHP outbound HTTP covers Laravel ",[160,460,461],{},"Http",[160,463,464],{},"Factory",[160,466,467],{},"PendingRequest"," and Guzzle. Symfony HttpClient, ",[160,470,471],{},"curl_*",[160,473,474],{},"file_get_contents"," are not client endpoints. A base URL that does not resolve is kept (",[160,477,478],{},"origin_kind"," ",[160,481,482],{},"unknown",[160,484,162],{},") and is not matched by host. The sample base comes from ",[160,487,289],{}," or an ",[160,490,293],{}," default; ",[160,493,494],{},".env"," is not read. A client verb ",[160,497,498],{},"ANY"," matches only when one route fits the path (",[160,501,162],{},[153,503,504,505,508,509,512,513,301,516,301,519,301,522,525],{},"Mail and SMS API clients (",[160,506,507],{},"external:saas:\u003Cprovider>",") are found when the client is built and used in one file. A client created in a factory and passed in is not followed, a ",[160,510,511],{},"send()"," on an untyped receiver is not guessed, and Laravel mailers other than ",[160,514,515],{},"mailgun",[160,517,518],{},"postmark",[160,520,521],{},"resend",[160,523,524],{},"ses"," are skipped (SMTP is a separate system).",[153,527,528,529,532,533,536,537,540,541,290,544,547,548,551],{},"Push, Firebase, Kubernetes, Docker and key-management clients (#42 part 3b) are found by regex on the client built and used in one file. Firebase server SDKs only: browser and mobile client SDKs are not systems. A Firebase init in another file is used only when every init in the project agrees on the credential, a collection, vault or secret name that is not a literal or env key is left off the node id, and a Kubernetes or Docker client passed in from a factory is not followed. A kubeconfig, service-account or key path written in the code is a ",[160,530,531],{},"credential_source"," of ",[160,534,535],{},"file"," with no ",[160,538,539],{},"CREDENTIAL_FROM",". Left out: Rust, Kotlin, Swift and Dart SDK libraries (",[160,542,543],{},"aws-sdk-*",[160,545,546],{},"google-cloud-*",", Firebase Android \u002F iOS, Soto, ",[160,549,550],{},"firebase_*","), Expo push from Python and PHP, and AWS KMS or GCP Secret Manager from PHP beyond the call shapes above.",[153,553,554,555,301,558,561,562,301,565,568,569,479,572,301,575,578,579,290,582,585,586,301,589,592,593,596,597,600],{},"TS Node HTTP clients: ",[160,556,557],{},"http",[160,559,560],{},"https"," options must be an object literal (or a const object) with a readable ",[160,563,564],{},"hostname",[160,566,567],{},"host","; ",[160,570,571],{},"undici",[160,573,574],{},"Client",[160,576,577],{},"Pool"," are followed when built from a variable or class field initialiser; ",[160,580,581],{},"agent",[160,583,584],{},"socketPath"," and raw ",[160,587,588],{},"net",[160,590,591],{},"tls"," sockets are not. A host that is not a literal, ",[160,594,595],{},"process.env"," value or const map is a ",[160,598,599],{},"ts_unrecognised_http_client"," blind spot.",[153,602,603,604,608,609,290,612,615,616,264,619,622,623,290,626,629,630,634,635,638],{},"Payload checks run for a single route match (",[199,605,607],{"href":606},"\u002Fdocs\u002Farchitecture#payload--field-check","payload \u002F field check","). Ambiguous matches are skipped. An opaque or partial body (a spread, ",[160,610,611],{},"Object.assign",[160,613,614],{},"FormData",", a value built in another function) does not produce ",[160,617,618],{},"request_missing_required",[160,620,621],{},"request_unknown_field",". ",[160,624,625],{},"sometimes",[160,627,628],{},"nullable",", and conditional rules do not count as missing. A route parameter is not a body or query key. A Laravel handler's query \u002F body reads count as known keys (",[199,631,633],{"href":632},"\u002Fdocs\u002Fphp#request-keys-the-handler-reads","which reads","), and an unknown query key is ",[160,636,637],{},"low"," and only reported when the route has explicit validation. An Elysia model-map value is followed through one const hop (same module or one import \u002F re-export); a longer chain or a computed map stays unknown, and an unresolved Elysia model name is not an empty schema.",[153,640,641,642,645,646,649,650,653,654,657,658,661,662,666,667,670,671,673,674,676,677,680],{},"Webhook receivers include Cashier ",[160,643,644],{},"handle\u003CEvent>"," methods on a ",[160,647,648],{},"WebhookController"," subclass, spatie\u002Flaravel-webhook-client jobs and profiles (a custom validator only when that class checks a signature), verifying middleware by alias, class name or body, Kotlin ",[160,651,652],{},"when"," and Rust ",[160,655,656],{},"match"," on an event header or field, signature headers named by a constant in the same class or module or an import, spatie route attributes, and dotted plugin ",[160,659,660],{},"router.post(\"name.action\")"," paths (",[199,663,665],{"href":664},"\u002Fdocs\u002Fprotocols#webhook-verification","Webhook verification","). A sender that reads its event from a stored subscription sends the events the repo declares (validation enum or list, config, seed data) and keeps ",[160,668,669],{},"{event}"," when none is declared; subscriber URLs in seed data, config and ",[160,672,289],{}," pair with routes in ",[160,675,444],{},"; a callback URL built from the app's own base becomes ",[160,678,679],{},"REGISTERS_CALLBACK","; and a payment webhook dispatched through a driver resolved at run time takes its checks and events from every implementation of the method. A callback URL built in a helper the function only calls, and drivers that share no interface or base class, are not followed.",[153,682,683],{},"Server shapes are the declared schema or a returned literal. Framework error bodies (validation 422, auth 401, 500 pages) are absent.",[153,685,686,687,690,691,301,694,697],{},"Enum checks need ",[160,688,689],{},"choices="," or a ",[160,692,693],{},"Literal",[160,695,696],{},"Enum"," annotation.",[153,699,700,701,290,704,707],{},"A route guard is a fact the framework plugin recorded on the route: middleware, Nest guards, ",[160,702,703],{},"Depends",[160,705,706],{},"auth=",", permission classes.",[153,709,710,711,714,715,718,719,290,722,725,726,301,729,732,733,736,737,290,740,301,743,746,747,301,750,753,754,264,757,532,760,301,763,765,766,301,769,772,773,775,776,779,780,253],{},"Laravel checks the action runs before its own work are inline guards, printed under ",[160,712,713],{},"guards:"," as ",[160,716,717],{},"inline:",". That includes ",[160,720,721],{},"authorize",[160,723,724],{},"Gate"," with an abort, ",[160,727,728],{},"abort_if",[160,730,731],{},"abort_unless"," with a permission, a FormRequest ",[160,734,735],{},"authorize()"," that returns more than ",[160,738,739],{},"true",[160,741,742],{},"$this->middleware(...)",[160,744,745],{},"HasMiddleware::middleware()"," on the controller (",[160,748,749],{},"only",[160,751,752],{},"except",", including resource and invokable actions), a project check that rejects or whose result the caller aborts on, and a shared-secret ",[160,755,756],{},"hash_equals",[160,758,759],{},"===",[160,761,762],{},"config()",[160,764,293],{}," against a header or input. A discarded ",[160,767,768],{},"can()",[160,770,771],{},"Gate::allows()"," result, a check after a write, and a ",[160,774,759],{}," between two request values are not guards. A check in a branch is ",[160,777,778],{},"conditional",". See ",[199,781,79],{"href":246},[153,783,784,785,290,788,791],{},"A check inside the handler in other frameworks (",[160,786,787],{},"if (!req.user)",[160,789,790],{},"request.user.is_authenticated",") is not a guard.",[153,793,794,795,797,798,801,802,805,806,809,810,813,814,243,816,818],{},"Project-wide defaults are not copied onto each route in ",[160,796,242],{},": Laravel kernel groups, Django ",[160,799,800],{},"MIDDLEWARE",", DRF ",[160,803,804],{},"DEFAULT_PERMISSION_CLASSES",". (",[160,807,808],{},"cg surface"," reads DRF, Laravel and Nest defaults itself; see ",[199,811,107],{"href":812},"#attack-surface",".) Controller ",[160,815,742],{},[160,817,745],{}," are copied onto that controller's routes as inline guards.",[153,820,821,824,825,828,829,203],{},[160,822,823],{},"cg routes --unguarded"," hides a route with an unconditional inline check. ",[160,826,827],{},"--unguarded --strict"," uses route guards only. Preset lists decide which middleware names count as auth (",[199,830,832],{"href":831},"\u002Fdocs\u002Fconfiguration#framework-presets","framework presets",[153,834,835,836,264,839,253],{},"A project-specific guard name counts when it matches ",[160,837,838],{},"auth.extra_patterns",[160,840,841],{},"--auth-pattern",[153,843,844],{},"A sent-but-not-forwarded key is an object literal passed to a helper whose request keys are known, one call level deep. Spreads, runtime keys, and opaque objects are omitted, so no gap is reported for them.",[153,846,847,848,851,852,855,856,859,860,863],{},"A realtime subscription wrapper (the channel is a parameter of the function that calls ",[160,849,850],{},"echo.private(name)",") is expanded at its call sites, with one extra wrapper level. A third level, a call-site argument that is not a literal or template (a runtime value), a wrapper stored in an object or passed as a callback, and pusher-js ",[160,853,854],{},"subscribe"," wrappers stay unresolved: no ",[160,857,858],{},"channel_sub"," is emitted and ",[160,861,862],{},"cg coverage --details"," counts the call site.",[145,865,107],{"id":866},"attack-surface",[150,868,869,896,1000,1035,1125,1154,1168,1171],{},[153,870,871,873,874,877,878,479,881,884,885,888,889,892,893,895],{},[160,872,808],{}," reads recorded facts plus a regex pass (",[160,875,876],{},"insecure_transport",") over source and config files. The pass finds disabled TLS and SSH host-key verification, plaintext gRPC channels, ",[160,879,880],{},"postMessage",[160,882,883],{},"'*'",", wildcard ",[160,886,887],{},"externally_connectable",", and Electron ",[160,890,891],{},"webPreferences",". It reads text, not types: a flag set through a variable, a wrapper, or a non-literal target is not seen, and a gRPC target that is not a literal is counted but not reported. Test files are skipped and counted. ",[160,894,494],{}," files are never read. Numeric validation limits are not detected yet.",[153,897,898,901,902,905,906,909,910,913,914,916,917,919,920,923,924,301,927,301,930,933,934,937,938,941,942,945,946,949,950,301,953,956,957,301,960,301,963,966,967,970,971,301,974,301,977,301,980,301,983,301,986,301,989,301,992,995,996,999],{},[160,899,900],{},"ssrf"," is a text-level taint walk per function (",[160,903,904],{},"cg_code_graph\u002Fssrf_input.py","), not a type analysis. It detects request input (Express \u002F Nest \u002F Next \u002F h3 \u002F Hono \u002F Elysia, Laravel \u002F ",[160,907,908],{},"$_GET",", Django \u002F Flask \u002F FastAPI parameters) that picks the host or the whole URL of ",[160,911,912],{},"fetch"," \u002F axios \u002F got \u002F undici \u002F node http, Laravel ",[160,915,461],{}," \u002F Guzzle \u002F curl \u002F ",[160,918,474],{},", and requests \u002F httpx \u002F aiohttp \u002F ",[160,921,922],{},"urlopen"," calls, and DNS lookups of input; it follows local variables, template \u002F concatenation \u002F ",[160,925,926],{},"sprintf",[160,928,929],{},"new URL",[160,931,932],{},"urljoin",", and one helper level through a ",[160,935,936],{},"CALLS"," edge. It does not follow a value through a second helper, a class field, a queue or a database, an assignment that spans several lines, or a client built elsewhere (",[160,939,940],{},"axios.create",", a Guzzle ",[160,943,944],{},"base_uri","), and an SDK ",[160,947,948],{},"endpoint"," \u002F bucket host from input is not read. A value that passes through the result of a call is still tainted when the input is only an argument of that call (an OAuth client building an authorization URL from its own settings is reported). An allow-list is recognised as a comparison with a constant or a name containing ",[160,951,952],{},"allow",[160,954,955],{},"trusted",", or a ",[160,958,959],{},"startsWith",[160,961,962],{},"startswith",[160,964,965],{},"str_starts_with"," check against a literal ",[160,968,969],{},"http(s):\u002F\u002F"," prefix, before the call; a regex test is not seen, so a validated call can still be reported. A value wrapped in ",[160,972,973],{},"realpath",[160,975,976],{},"basename",[160,978,979],{},"intval",[160,981,982],{},"(int)",[160,984,985],{},"parseInt",[160,987,988],{},"Number",[160,990,991],{},"int",[160,993,994],{},"float"," is not a URL. Nuxt ",[160,997,998],{},"server\u002F"," handlers give facts but no entry points, because they are not modelled as routes.",[153,1001,1002,1005,1006,290,1009,290,1012,290,1015,1018,1019,1022,1023,1026,1027,1031,1032,1034],{},[160,1003,1004],{},"hardcoded"," sees the credentials the external-system and SDK extractors flag as literal, DSNs with a password, and Laravel config literals. A literal in a Python or TypeScript settings value that no extractor ties to a system is not reported, and the config check is by key name (",[160,1007,1008],{},"password",[160,1010,1011],{},"token",[160,1013,1014],{},"secret",[160,1016,1017],{},"*_key","). Not reported either: a ",[160,1020,1021],{},"getenv('X') ?: 'literal'"," default outside Laravel config, a secret in a plain JavaScript config object (",[160,1024,1025],{},"cookieSecret","), and a test account in client code. The ",[199,1028,1030],{"href":1029},"\u002Fdocs\u002Fvalidation-log#attack-surface-47","validation log"," lists what the three vulnerable demo apps document and ",[160,1033,808],{}," misses.",[153,1036,1037,1040,1041,1044,1045,243,1048,1051,1052,1054,1055,1057,1058,1061,1062,1065,1066,290,1069,1072,1073,243,1076,1079,1080,1083,1084,1087,1088,301,1091,1094,1095,1098,1099,1102,1103,1105,1106,1109,1110,1113,1114,1117,1118,1121,1122,1124],{},[160,1038,1039],{},"plaintext"," needs a known non-loopback host and ",[160,1042,1043],{},"tls=false",". A host from an environment variable - ",[160,1046,1047],{},"unguarded",[160,1049,1050],{},"unverified"," follow the guard facts of ",[199,1053,252],{"href":251},", refined by ",[160,1056,808],{}," (unless ",[160,1059,1060],{},"--strict",") with: a Django REST framework ",[160,1063,1064],{},"REST_FRAMEWORK"," default permission class, Laravel global and group middleware (",[160,1067,1068],{},"app\u002FHttp\u002FKernel.php",[160,1070,1071],{},"bootstrap\u002Fapp.php","), a Nest ",[160,1074,1075],{},"APP_GUARD",[160,1077,1078],{},"@Public()",", an Express ",[160,1081,1082],{},"app.use(auth)"," that comes before the route and matches its mount path, a check in the first statements of a handler or of a Socket.IO connection (a session, token, role or permission test, a ",[160,1085,1086],{},"getServerSession"," call, a ",[160,1089,1090],{},"403",[160,1092,1093],{},"401"," response), and a table of public-by-design routes (",[199,1096,107],{"href":1097},"\u002Fdocs\u002Fsurface#public-by-design-routes","). Only a check that the index recognises counts; any other middleware or a call that merely looks like a check (",[160,1100,1101],{},"checkAuth()"," in a name, a GraphQL endpoint, a webhook receiver whose verification is not recognised) makes the finding ",[160,1104,162],{}," and low severity. Express ",[160,1107,1108],{},"session()"," alone is not authentication. Protocols that record no guards show ",[160,1111,1112],{},"unchecked"," and are never reported unguarded. Not seen: a check beyond the first 14 lines of a handler or in a helper two calls away, a check in another file reached through a wrapper, a per-object permission test, a role check on a route that already has a login guard, tRPC procedure middleware, and a setting such as netbox's ",[160,1115,1116],{},"LOGIN_REQUIRED"," that decides at run time. On the sampled corpora the findings that remain after these rules are low severity and mostly false positives or unclear (",[199,1119,1030],{"href":1120},"\u002Fdocs\u002Fvalidation-log#part-2d-unguarded-precision-index-time-fingerprints","), so treat ",[160,1123,1047],{}," as a list to review, not a gate. File-per-page PHP apps have no modelled routes and show no inbound surface.ct many false positives on large apps. File-per-page PHP apps have no modelled routes and show no inbound surface.",[153,1126,1127,1130,1131,1134,1135,1138,1139,243,1141,1143,1144,290,1147,1149,1150,1153],{},[160,1128,1129],{},"tls-off"," reports the code path, not whether it is reached: ",[160,1132,1133],{},"verify=False"," behind a user option is reported, as is a ",[160,1136,1137],{},"StrictHostKeyChecking=no"," in a conditional. Python text inside docstrings, triple-quoted strings and import lines is skipped. ",[160,1140,1039],{},[160,1142,1004],{}," also read example env files (",[160,1145,1146],{},".env.sample",[160,1148,289],{},"), so a placeholder DSN there is reported; a plain ",[160,1151,1152],{},"http.createServer"," is not a plaintext finding.",[153,1155,1156,1157,1160,1161,1164,1165,1167],{},"The redaction marker is ",[160,1158,1159],{},"redacted:hmac:\u003C8 hex>",", an HMAC-SHA-256 of the value keyed by a per-graph salt (meta ",[160,1162,1163],{},"redact_salt","). It tells two values apart within one graph, and a common password cannot be recognised from it without the salt, which is in the same database. It is not comparable across graphs: the same secret gives different markers in two graphs, and a ",[160,1166,444],{}," combined graph keeps the markers of its sources without a salt of its own, so cross-repo comparison of fingerprints is not supported. A fixed-width marker of 8 hex characters is short: it can collide, and it is a hint, not an identifier. Example DSNs in doc comments are redacted like any other URL password.",[153,1169,1170],{},"Follow-ups that stay open: Nuxt \u002F h3 file-based entry points; multi-line assignments in the PHP and Python regex flow of the SSRF pass; SDK endpoint and bucket-host sinks; file-per-page PHP routes; taint through the result of a call.",[153,1172,1173],{},"On a combined graph two repos naming the same external address share one node, so a credential literal recorded on the node belongs to the first repo; literal credentials passed at a call site keep their own repo and file.",[145,1175,1177],{"id":1176},"plans-value-facts-and-the-visual-view","Plans, value facts, and the visual view",[150,1179,1180,1189,1195,1205,1208,1211,1217,1269,1279,1282,1285],{},[153,1181,1182,1183,1186,1187,203],{},"Plan completeness rules are the named set: writers, readers, callers, clients, mirrors, identity columns, text mentions, and declared precedents. Anything else needs a plan entry or a ",[160,1184,1185],{},"precedents"," regex (",[199,1188,83],{"href":84},[153,1190,1191,1194],{},[160,1192,1193],{},"role: guard"," sees a graph read of the declared column by the guard method or a direct callee. Whether that branch blocks the path is left to the reader.",[153,1196,1197,1200,1201,1204],{},[160,1198,1199],{},"--verify"," reports changed and unchanged spans against the baseline, plus the planned edges. The free-text ",[160,1202,1203],{},"intent"," stays with the reviewer.",[153,1206,1207],{},"External clients come from the snapshot file. Private repos are not indexed for that list.",[153,1209,1210],{},"Findings come from a hand-refreshed snapshot of issue evidence lines, mapped to the innermost function span.",[153,1212,1213,1214,253],{},"Plan text mentions match exact names (identity columns, relation names) inside ",[160,1215,1216],{},"plans.text_mention_dirs",[153,1218,1219,1220,1223,1224,1227,1228,1231,1232,1235,1236,1239,1240,1242,1243,301,1246,1249,1250,1252,1253,1256,1257,1260,1261,1264,1265,1268],{},"Mass-assignment column writes (#177) take their keys from FormRequest ",[160,1221,1222],{},"rules()"," and inline ",[160,1225,1226],{},"validate([...])",": keys added at run time (",[160,1229,1230],{},"$data[$field] = ..."," in a loop, ",[160,1233,1234],{},"Arr::only($data, $allowed)"," with a computed list), model mutators and ",[160,1237,1238],{},"$casts"," that write other columns, and ",[160,1241,1222],{}," that is not a returned array literal are not followed. ",[160,1244,1245],{},"$request->all()",[160,1247,1248],{},"input()"," is ",[160,1251,162],{}," and uses ",[160,1254,1255],{},"$fillable"," (there is no filter by rules). ",[160,1258,1259],{},"new Model($data)"," counts only when the same function calls ",[160,1262,1263],{},"save()"," on it. Other frameworks (Django ",[160,1266,1267],{},"Model.objects.create(**form.cleaned_data)",", Rails strong params) are not covered.",[153,1270,1271,1272,1275,1276,203],{},"Value-fact concept match is the head word of the target, or of the first source key. ",[160,1273,1274],{},"--within"," is a substring filter (",[199,1277,1278],{"href":128},"Value facts",[153,1280,1281],{},"The \"returns\" form treats source order as fallback order. Locals keep their last assignment. Helper inlining stops at depth 4.",[153,1283,1284],{},"A setting → API response → client chain is not followed. Response fields are not nodes.",[153,1286,1287,1288,1291,1292,203],{},"The visual view is comfortable at a few hundred nodes. Above about 1,500 it keeps the closest ones (",[160,1289,1290],{},"truncated","). The server binds to localhost and has no auth (",[199,1293,131],{"href":132},[145,1295,1297],{"id":1296},"language-pages","Language pages",[1299,1300,1301,1314],"table",{},[1302,1303,1304],"thead",{},[1305,1306,1307,1311],"tr",{},[1308,1309,1310],"th",{},"area",[1308,1312,1313],{},"page",[1315,1316,1317,1327,1336,1345,1354,1362,1370,1378,1388,1397,1406],"tbody",{},[1305,1318,1319,1323],{},[1320,1321,1322],"td",{},"Python roots, references, routes",[1320,1324,1325],{},[199,1326,95],{"href":96},[1305,1328,1329,1332],{},[1320,1330,1331],{},"PHP properties",[1320,1333,1334],{},[199,1335,79],{"href":80},[1305,1337,1338,1341],{},[1320,1339,1340],{},"TypeScript servers",[1320,1342,1343],{},[199,1344,115],{"href":116},[1305,1346,1347,1350],{},[1320,1348,1349],{},"Rust, C, C++",[1320,1351,1352],{},[199,1353,71],{"href":72},[1305,1355,1356,1358],{},[1320,1357,54],{},[1320,1359,1360],{},[199,1361,54],{"href":55},[1305,1363,1364,1366],{},[1320,1365,50],{},[1320,1367,1368],{},[199,1369,50],{"href":51},[1305,1371,1372,1374],{},[1320,1373,111],{},[1320,1375,1376],{},[199,1377,111],{"href":112},[1305,1379,1380,1383],{},[1320,1381,1382],{},"Platforms and variants",[1320,1384,1385],{},[199,1386,1387],{"href":88},"Platforms",[1305,1389,1390,1393],{},[1320,1391,1392],{},"Channels and tests",[1320,1394,1395],{},[199,1396,1392],{"href":23},[1305,1398,1399,1402],{},[1320,1400,1401],{},"Protocols",[1320,1403,1404],{},[199,1405,91],{"href":92},[1305,1407,1408,1411],{},[1320,1409,1410],{},"Bridges",[1320,1412,1413],{},[199,1414,18],{"href":19},{"title":1416,"searchDepth":1417,"depth":1418,"links":1419},"",4,2,[1420,1421,1422,1423,1424,1425,1426,1427],{"id":147,"depth":1418,"text":148},{"id":193,"depth":1418,"text":194},{"id":230,"depth":1418,"text":231},{"id":317,"depth":1418,"text":318},{"id":437,"depth":1418,"text":252},{"id":866,"depth":1418,"text":107},{"id":1176,"depth":1418,"text":1177},{"id":1296,"depth":1418,"text":1297},"md",{},true,{"title":58,"description":143},"8q10Vs7NS-yUbUnU8dF1Ny6S3klH2UMpBdHU4hd3lA4",[1434,1436],{"title":54,"path":55,"stem":56,"description":1435,"children":-1},"What .kt \u002F .kts add beyond Install, CLI specs, and Graph schema: heuristic vs scip-java, the env flags, and the ids those pages do not spell out. Toolchain fit: cg doctor -h. Why a file stayed heuristic: cg coverage.",{"title":62,"path":63,"stem":64,"children":-1,"description":1437},"code-graph ships a stdio Model Context Protocol server. An agent gets callers, entry points and file:line evidence from the graph. It needs the mcp Python SDK (2.x). Use the installed cg-mcp command from Install.",1792170234485]