[{"data":1,"prerenderedAt":1882},["ShallowReactive",2],{"page-\u002Fworkflows\u002Fmodules":3,"all-pages":1549},{"id":4,"title":5,"body":6,"description":1540,"extension":1541,"meta":1542,"navigation":65,"path":1543,"robots":1544,"seo":1545,"sitemap":1546,"stem":1547,"__hash__":1548},"content\u002F01.workflows\u002F08.modules.md","Modules",{"type":7,"value":8,"toc":1526},"minimark",[9,13,18,31,145,148,186,189,270,288,325,334,337,359,366,410,421,428,437,447,494,499,510,522,544,548,555,605,629,633,658,734,749,752,795,798,864,867,897,902,938,942,945,1014,1074,1081,1214,1218,1232,1236,1297,1306,1310,1317,1478,1482,1485,1522],[10,11,12],"p",{},"Once you have hunted for a while, you will notice you rewrite the same phase in\nevery workflow: probe a list of hosts, screenshot them, enumerate a domain.\nModules let you package such a phase once — with an explicit input\u002Foutput\ncontract — and reuse it everywhere, or publish it for other hunters.",[14,15,17],"h2",{"id":16},"defining-a-module","Defining a Module",[10,19,20,21,25,26,30],{},"A module is a Starlark file whose value is a ",[22,23,24],"code",{},"module(...)"," definition. It\ndeclares its public contract with ",[27,28,29],"strong",{},"symbolic"," input and output references:",[32,33,38],"pre",{"className":34,"code":35,"language":36,"meta":37,"style":37},"language-bhw shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# module: projectdiscover\u002Fhttp-probe\ndomain = input.string(name = \"domain\", description = \"Domain to enumerate\")\ndomains = output.file(name = \"domains\", description = \"Discovered subdomains\")\n\nmodule(\n    inputs = [domain],\n    outputs = [domains],\n    steps = [\n        step.exec(command = [\"subfinder\", \"-d\", domain, \"-o\", \"subs-raw.txt\"]),\n        step.transform(\n            source = path.file(\"subs-raw.txt\").lines(),\n            pipeline = transform.trim().lower().unique().sort(),\n            destination = path.file(\"subs.txt\"),\n        ),\n        step.output(domains, path = path.file(\"subs.txt\")),\n    ],\n)\n","bhw","",[22,39,40,48,54,60,67,73,79,85,91,97,103,109,115,121,127,133,139],{"__ignoreMap":37},[41,42,45],"span",{"class":43,"line":44},"line",1,[41,46,47],{},"# module: projectdiscover\u002Fhttp-probe\n",[41,49,51],{"class":43,"line":50},2,[41,52,53],{},"domain = input.string(name = \"domain\", description = \"Domain to enumerate\")\n",[41,55,57],{"class":43,"line":56},3,[41,58,59],{},"domains = output.file(name = \"domains\", description = \"Discovered subdomains\")\n",[41,61,63],{"class":43,"line":62},4,[41,64,66],{"emptyLinePlaceholder":65},true,"\n",[41,68,70],{"class":43,"line":69},5,[41,71,72],{},"module(\n",[41,74,76],{"class":43,"line":75},6,[41,77,78],{},"    inputs = [domain],\n",[41,80,82],{"class":43,"line":81},7,[41,83,84],{},"    outputs = [domains],\n",[41,86,88],{"class":43,"line":87},8,[41,89,90],{},"    steps = [\n",[41,92,94],{"class":43,"line":93},9,[41,95,96],{},"        step.exec(command = [\"subfinder\", \"-d\", domain, \"-o\", \"subs-raw.txt\"]),\n",[41,98,100],{"class":43,"line":99},10,[41,101,102],{},"        step.transform(\n",[41,104,106],{"class":43,"line":105},11,[41,107,108],{},"            source = path.file(\"subs-raw.txt\").lines(),\n",[41,110,112],{"class":43,"line":111},12,[41,113,114],{},"            pipeline = transform.trim().lower().unique().sort(),\n",[41,116,118],{"class":43,"line":117},13,[41,119,120],{},"            destination = path.file(\"subs.txt\"),\n",[41,122,124],{"class":43,"line":123},14,[41,125,126],{},"        ),\n",[41,128,130],{"class":43,"line":129},15,[41,131,132],{},"        step.output(domains, path = path.file(\"subs.txt\")),\n",[41,134,136],{"class":43,"line":135},16,[41,137,138],{},"    ],\n",[41,140,142],{"class":43,"line":141},17,[41,143,144],{},")\n",[10,146,147],{},"Reading it:",[149,150,151,174,180],"ul",{},[152,153,154,157,158,161,162,166,167,170,171,173],"li",{},[22,155,156],{},"input.string(name = \"domain\", ...)"," creates an ",[22,159,160],{},"InputRef"," — the module's\n",[163,164,165],"em",{},"public"," input named ",[22,168,169],{},"domain",". It is independent of the Starlark variable it\nis assigned to (",[22,172,169],{}," here is just a handle for referencing it below).",[152,175,176,179],{},[22,177,178],{},"output.file(name = \"domains\", ...)"," declares a file output.",[152,181,182,185],{},[22,183,184],{},"step.output(domains, path = path.file(\"subs.txt\"))"," assigns the declared\noutput to an actual file produced inside the module. Each declared output\nmust be assigned exactly once.",[10,187,188],{},"Input declarations:",[190,191,192,208],"table",{},[193,194,195],"thead",{},[196,197,198,202,205],"tr",{},[199,200,201],"th",{},"Declaration",[199,203,204],{},"Produces",[199,206,207],{},"Notes",[209,210,211,233,245,258],"tbody",{},[196,212,213,219,222],{},[214,215,216],"td",{},[22,217,218],{},"input.string(name, default, required, description, secret)",[214,220,221],{},"String input",[214,223,224,225,228,229,232],{},"Required iff no ",[22,226,227],{},"default","; ",[22,230,231],{},"secret = True"," marks a credential",[196,234,235,240,243],{},[214,236,237],{},[22,238,239],{},"input.bool(name, default, required, description)",[214,241,242],{},"Bool input",[214,244],{},[196,246,247,252,255],{},[214,248,249],{},[22,250,251],{},"input.file(name, required, description)",[214,253,254],{},"File input",[214,256,257],{},"Required by default",[196,259,260,265,268],{},[214,261,262],{},[22,263,264],{},"input.directory(name, required, description)",[214,266,267],{},"Directory input",[214,269,257],{},[10,271,272,273,276,277,280,281,283,284,287],{},"Callers may bind a string input from a literal or from configuration:\n",[22,274,275],{},"config.var(...)"," \u002F ",[22,278,279],{},"config.secret(...)"," are accepted wherever a string input\nis expected. Mark credential inputs with ",[22,282,231],{}," (the default is\n",[22,285,286],{},"False","):",[32,289,291],{"className":34,"code":290,"language":36,"meta":37,"style":37},"api_token = input.string(name = \"api_token\", required = False, secret = True)\n\nmodule(\n    inputs = [api_token],\n    outputs = [],\n    steps = [step.exec(command = [\"tool\"], env = {\"API_TOKEN\": api_token})],\n)\n",[22,292,293,298,302,306,311,316,321],{"__ignoreMap":37},[41,294,295],{"class":43,"line":44},[41,296,297],{},"api_token = input.string(name = \"api_token\", required = False, secret = True)\n",[41,299,300],{"class":43,"line":50},[41,301,66],{"emptyLinePlaceholder":65},[41,303,304],{"class":43,"line":56},[41,305,72],{},[41,307,308],{"class":43,"line":62},[41,309,310],{},"    inputs = [api_token],\n",[41,312,313],{"class":43,"line":69},[41,314,315],{},"    outputs = [],\n",[41,317,318],{"class":43,"line":75},[41,319,320],{},"    steps = [step.exec(command = [\"tool\"], env = {\"API_TOKEN\": api_token})],\n",[41,322,323],{"class":43,"line":81},[41,324,144],{},[32,326,328],{"className":34,"code":327,"language":36,"meta":37,"style":37},"step.module(tool, inputs = {\"api_token\": config.secret(\"api_token\")})\n",[22,329,330],{"__ignoreMap":37},[41,331,332],{"class":43,"line":44},[41,333,327],{},[10,335,336],{},"Output declarations:",[190,338,339,347],{},[193,340,341],{},[196,342,343,345],{},[199,344,201],{},[199,346,204],{},[209,348,349],{},[196,350,351,356],{},[214,352,353],{},[22,354,355],{},"output.file(name, description)",[214,357,358],{},"File (path) output",[10,360,361,362,365],{},"Inputs are not limited to argv: they integrate with the string expression\nsystem, so ",[22,363,364],{},".format(...)"," and concatenation work too:",[32,367,369],{"className":34,"code":368,"language":36,"meta":37,"style":37},"target_url = input.string(name = \"target_url\", description = \"Base URL to crawl\")\n\nmodule(\n    inputs = [target_url],\n    outputs = [],\n    steps = [\n        step.exec(command = [\"katana\", \"-u\", target_url, \"-d\", \"3\"]),\n    ],\n)\n",[22,370,371,376,380,384,389,393,397,402,406],{"__ignoreMap":37},[41,372,373],{"class":43,"line":44},[41,374,375],{},"target_url = input.string(name = \"target_url\", description = \"Base URL to crawl\")\n",[41,377,378],{"class":43,"line":50},[41,379,66],{"emptyLinePlaceholder":65},[41,381,382],{"class":43,"line":56},[41,383,72],{},[41,385,386],{"class":43,"line":62},[41,387,388],{},"    inputs = [target_url],\n",[41,390,391],{"class":43,"line":69},[41,392,315],{},[41,394,395],{"class":43,"line":75},[41,396,90],{},[41,398,399],{"class":43,"line":81},[41,400,401],{},"        step.exec(command = [\"katana\", \"-u\", target_url, \"-d\", \"3\"]),\n",[41,403,404],{"class":43,"line":87},[41,405,138],{},[41,407,408],{"class":43,"line":93},[41,409,144],{},[14,411,413,414,417,418],{"id":412},"invoking-a-module-load-stepmodule","Invoking a Module: ",[22,415,416],{},"load"," + ",[22,419,420],{},"step.module",[10,422,423,424,427],{},"Modules are loaded from a registry with ",[22,425,426],{},"load()",". Loading is purely an import —\nit never executes anything:",[32,429,431],{"className":34,"code":430,"language":36,"meta":37,"style":37},"load(\"projectdiscover\u002Fhttp-probe\", \"http_probe\")\n",[22,432,433],{"__ignoreMap":37},[41,434,435],{"class":43,"line":44},[41,436,430],{},[10,438,439,440,443,444,446],{},"The first argument is ",[22,441,442],{},"\"publisher\u002Fmodule-name\"","; the second binds it to a local\nname. Instantiate it with ",[22,445,420],{},", binding inputs against its contract:",[32,448,450],{"className":34,"code":449,"language":36,"meta":37,"style":37},"activity(\n    name = \"discover\",\n    triggers = [trigger.dispatch()],\n    steps = [\n        step.module(http_probe, inputs = {\n            \"domain\": config.var(\"target_domain\"),\n        }),\n    ],\n)\n",[22,451,452,457,462,467,471,476,481,486,490],{"__ignoreMap":37},[41,453,454],{"class":43,"line":44},[41,455,456],{},"activity(\n",[41,458,459],{"class":43,"line":50},[41,460,461],{},"    name = \"discover\",\n",[41,463,464],{"class":43,"line":56},[41,465,466],{},"    triggers = [trigger.dispatch()],\n",[41,468,469],{"class":43,"line":62},[41,470,90],{},[41,472,473],{"class":43,"line":69},[41,474,475],{},"        step.module(http_probe, inputs = {\n",[41,477,478],{"class":43,"line":75},[41,479,480],{},"            \"domain\": config.var(\"target_domain\"),\n",[41,482,483],{"class":43,"line":81},[41,484,485],{},"        }),\n",[41,487,488],{"class":43,"line":87},[41,489,138],{},[41,491,492],{"class":43,"line":93},[41,493,144],{},[10,495,496,498],{},[22,497,420],{}," validates at save time:",[149,500,501,504,507],{},[152,502,503],{},"Unknown inputs are rejected.",[152,505,506],{},"Required inputs must be bound.",[152,508,509],{},"Values are type-checked against the declared input type.",[10,511,512,513,515,516,518,519,521],{},"Only modules imported with ",[22,514,426],{}," can be invoked. A ",[22,517,24],{}," value\ndefined locally in the same workflow file cannot be passed to ",[22,520,420],{},".",[10,523,524,525,528,529,532,533,536,537,540,541,521],{},"Module outputs become available to subsequent steps through the invocation,\ne.g. ",[22,526,527],{},"probe.outputs.domains"," for a module declaring a ",[22,530,531],{},"domains"," file output.\nA module with exactly one declared output also has ",[22,534,535],{},".output","\n(",[22,538,539],{},"probe.output","); with several, use ",[22,542,543],{},".outputs.\u003Cname>",[14,545,547],{"id":546},"isolation-and-file-handling","Isolation and File Handling",[10,549,550,551,554],{},"A module can come from another publisher, so it runs in its ",[27,552,553],{},"own isolated\nworkspace",":",[149,556,557,568,571,584,587,594],{},[152,558,559,560,563,564,567],{},"Every ",[22,561,562],{},"file","\u002F",[22,565,566],{},"directory"," input is copied into that workspace before the\nmodule runs. Nothing else is placed there, so files are never implicitly\nvisible; the module still runs as the runner user and can read what that user\ncan read (toolchains, config) at absolute paths.",[152,569,570],{},"The module can only write inside its own workspace.",[152,572,573,574,577,578,581,582,521],{},"Only outputs declared by the module are copied back to the caller. They land\nat ",[22,575,576],{},"\u003Cmodule-path>.\u003Coutput-name>"," (for example\n",[22,579,580],{},"projectdiscover\u002Fhttp-probe.domains",") and are reachable through the\ninvocation: ",[22,583,527],{},[152,585,586],{},"Undeclared files the module wrote are discarded with its workspace; there is\nno implicit shared directory. Pass everything a module needs as declared\ninputs, and never guess the producer's internal file name.",[152,588,589,590,593],{},"An output is an ordinary file reference: pass it to another module input, use\nit as a ",[22,591,592],{},"step.exec"," argv element, transform it, or use it as an artifact\nsource.",[152,595,596,597,600,601,604],{},"A declared output must exist when the module finishes. ",[22,598,599],{},"allow_failure"," on the\nproducing step only tolerates its exit code; a missing output file still\nfails the module. When a tool writes its own report file, create it first\n(for example ",[22,602,603],{},"step.exec(command = [\"touch\", \"report.json\"])",").",[32,606,608],{"className":34,"code":607,"language":36,"meta":37,"style":37},"probe = step.module(http_probe, inputs = {\"domain\": config.var(\"target_domain\")})\n\n# The caller never guesses \"domains.txt\": it uses the declared output.\nstep.exec(command = [\"cat\", probe.outputs.domains])\n",[22,609,610,615,619,624],{"__ignoreMap":37},[41,611,612],{"class":43,"line":44},[41,613,614],{},"probe = step.module(http_probe, inputs = {\"domain\": config.var(\"target_domain\")})\n",[41,616,617],{"class":43,"line":50},[41,618,66],{"emptyLinePlaceholder":65},[41,620,621],{"class":43,"line":56},[41,622,623],{},"# The caller never guesses \"domains.txt\": it uses the declared output.\n",[41,625,626],{"class":43,"line":62},[41,627,628],{},"step.exec(command = [\"cat\", probe.outputs.domains])\n",[14,630,632],{"id":631},"accessing-module-outputs","Accessing Module Outputs",[10,634,635,638,639,642,643,646,647,650,651,654,655,554],{},[22,636,637],{},"step.module(...)"," returns the ",[27,640,641],{},"invocation"," value, and that value is the only\nway to reach the module's outputs. A ",[22,644,645],{},"load(...)"," symbol is the module\n",[27,648,649],{},"definition",", not an invocation: it has no outputs. Bind the invocation to a\ndistinct variable and read ",[22,652,653],{},"\u003Cinvocation>.outputs.\u003Coutput-name>",", using a name\nthe module declared in ",[22,656,657],{},"outputs = [...]",[32,659,661],{"className":34,"code":660,"language":36,"meta":37,"style":37},"load(\"bountyhub\u002Fnaabu\", \"naabu\")\n\nnaabu_run = step.module(\n    naabu,\n    id = \"naabu\",\n    inputs = {\"hosts\": path.file(\"hosts.txt\")},\n)\n\nstep.update_dataset(\n    table = \"ports\",\n    source = naabu_run.outputs.ports,\n    pipeline = transform.lines(),\n    mapping = {\"port\": row},\n    mode = \"sync\",\n)\n",[22,662,663,668,672,677,682,687,692,696,700,705,710,715,720,725,730],{"__ignoreMap":37},[41,664,665],{"class":43,"line":44},[41,666,667],{},"load(\"bountyhub\u002Fnaabu\", \"naabu\")\n",[41,669,670],{"class":43,"line":50},[41,671,66],{"emptyLinePlaceholder":65},[41,673,674],{"class":43,"line":56},[41,675,676],{},"naabu_run = step.module(\n",[41,678,679],{"class":43,"line":62},[41,680,681],{},"    naabu,\n",[41,683,684],{"class":43,"line":69},[41,685,686],{},"    id = \"naabu\",\n",[41,688,689],{"class":43,"line":75},[41,690,691],{},"    inputs = {\"hosts\": path.file(\"hosts.txt\")},\n",[41,693,694],{"class":43,"line":81},[41,695,144],{},[41,697,698],{"class":43,"line":87},[41,699,66],{"emptyLinePlaceholder":65},[41,701,702],{"class":43,"line":93},[41,703,704],{},"step.update_dataset(\n",[41,706,707],{"class":43,"line":99},[41,708,709],{},"    table = \"ports\",\n",[41,711,712],{"class":43,"line":105},[41,713,714],{},"    source = naabu_run.outputs.ports,\n",[41,716,717],{"class":43,"line":111},[41,718,719],{},"    pipeline = transform.lines(),\n",[41,721,722],{"class":43,"line":117},[41,723,724],{},"    mapping = {\"port\": row},\n",[41,726,727],{"class":43,"line":123},[41,728,729],{},"    mode = \"sync\",\n",[41,731,732],{"class":43,"line":129},[41,733,144],{},[10,735,736,737,740,741,744,745,748],{},"Do not write ",[22,738,739],{},"naabu.outputs.ports",": ",[22,742,743],{},"naabu"," is the loaded definition. Prefer a\ndistinct invocation name (",[22,746,747],{},"naabu_run",") rather than shadowing the imported\nsymbol.",[10,750,751],{},"The same pattern chains modules:",[32,753,755],{"className":34,"code":754,"language":36,"meta":37,"style":37},"enum_run = step.module(\n    subdomain_enum,\n    inputs = {\"domain\": config.var(\"target_domain\")},\n)\nscan_run = step.module(\n    vuln_scan,\n    inputs = {\"targets\": enum_run.outputs.subs},\n)\n",[22,756,757,762,767,772,776,781,786,791],{"__ignoreMap":37},[41,758,759],{"class":43,"line":44},[41,760,761],{},"enum_run = step.module(\n",[41,763,764],{"class":43,"line":50},[41,765,766],{},"    subdomain_enum,\n",[41,768,769],{"class":43,"line":56},[41,770,771],{},"    inputs = {\"domain\": config.var(\"target_domain\")},\n",[41,773,774],{"class":43,"line":62},[41,775,144],{},[41,777,778],{"class":43,"line":69},[41,779,780],{},"scan_run = step.module(\n",[41,782,783],{"class":43,"line":75},[41,784,785],{},"    vuln_scan,\n",[41,787,788],{"class":43,"line":81},[41,789,790],{},"    inputs = {\"targets\": enum_run.outputs.subs},\n",[41,792,793],{"class":43,"line":87},[41,794,144],{},[10,796,797],{},"An output is a file reference, so it can be used anywhere a file resource is\naccepted:",[32,799,801],{"className":34,"code":800,"language":36,"meta":37,"style":37},"# As a module input (above), or as a step.exec argv element.\nstep.exec(command = [\"nuclei\", \"-l\", enum_run.outputs.subs])\n\n# As an artifact entry, to share the result with another activity.\nstep.upload_artifact(\n    name = \"findings\",\n    entries = [\n        artifact_entry(\n            source = scan_run.outputs.findings,\n            destination = path.file(\"findings.txt\"),\n        ),\n    ],\n)\n",[22,802,803,808,813,817,822,827,832,837,842,847,852,856,860],{"__ignoreMap":37},[41,804,805],{"class":43,"line":44},[41,806,807],{},"# As a module input (above), or as a step.exec argv element.\n",[41,809,810],{"class":43,"line":50},[41,811,812],{},"step.exec(command = [\"nuclei\", \"-l\", enum_run.outputs.subs])\n",[41,814,815],{"class":43,"line":56},[41,816,66],{"emptyLinePlaceholder":65},[41,818,819],{"class":43,"line":62},[41,820,821],{},"# As an artifact entry, to share the result with another activity.\n",[41,823,824],{"class":43,"line":69},[41,825,826],{},"step.upload_artifact(\n",[41,828,829],{"class":43,"line":75},[41,830,831],{},"    name = \"findings\",\n",[41,833,834],{"class":43,"line":81},[41,835,836],{},"    entries = [\n",[41,838,839],{"class":43,"line":87},[41,840,841],{},"        artifact_entry(\n",[41,843,844],{"class":43,"line":93},[41,845,846],{},"            source = scan_run.outputs.findings,\n",[41,848,849],{"class":43,"line":99},[41,850,851],{},"            destination = path.file(\"findings.txt\"),\n",[41,853,854],{"class":43,"line":105},[41,855,126],{},[41,857,858],{"class":43,"line":111},[41,859,138],{},[41,861,862],{"class":43,"line":117},[41,863,144],{},[10,865,866],{},"Rules:",[149,868,869,876,891],{},[152,870,871,872,875],{},"Only declared output names exist on ",[22,873,874],{},"outputs","; an undeclared name is a\ncompile-time error.",[152,877,878,879,882,883,886,887,890],{},"A module output is ",[27,880,881],{},"not"," an activity artifact.\n",[22,884,885],{},"\u003Cactivity>.artifacts.\u003Cname>"," exists only for a ",[22,888,889],{},"step.upload_artifact(name = \"\u003Cname>\", ...)"," call. To carry a module output to another activity, upload it\nas an artifact (as above) and download that artifact in the consumer.",[152,892,893,894,521],{},"Do not guess the file the module wrote; pass ",[22,895,896],{},"module.outputs.\u003Cname>",[898,899,901],"h3",{"id":900},"platform-modules","Platform modules",[10,903,904,905,908,909,912,913,916,917,920,921,924,925,928,929,932,933,604],{},"The platform publishes modules under the reserved ",[22,906,907],{},"bountyhub"," publisher, so\n",[22,910,911],{},"load(\"bountyhub\u002F\u003Cname>\", \"\u003Cname>\")"," resolves without you publishing anything.\nThat includes wrappers for agent CLIs — ",[22,914,915],{},"bountyhub\u002Fclaude",", ",[22,918,919],{},"bountyhub\u002Fcodex",",\n",[22,922,923],{},"bountyhub\u002Fhermes",", and ",[22,926,927],{},"bountyhub\u002Fopencode"," — which you invoke like\n",[22,930,931],{},"step.agent"," (see ",[934,935,937],"a",{"href":936},"\u002Fworkflows\u002Fagents","Agents",[14,939,941],{"id":940},"a-realistic-reusable-library","A Realistic Reusable Library",[10,943,944],{},"Split your methodology into composable modules mirroring how you actually\nhunt:",[32,946,948],{"className":34,"code":947,"language":36,"meta":37,"style":37},"# module: yourname\u002Fsubdomain-enum  — subfinder + permutation + validation\ndomain = input.string(name = \"domain\", description = \"Root domain\")\nsubs = output.file(name = \"subs\", description = \"Validated subdomains\")\n\nmodule(\n    inputs = [domain],\n    outputs = [subs],\n    steps = [\n        step.exec(command = [\"subfinder\", \"-d\", domain, \"-silent\", \"-o\", \"passive.txt\"]),\n        step.exec(command = [\"alterx\", \"-l\", \"passive.txt\", \"-o\", \"perms.txt\"]),\n        step.exec(command = [\"shuffledns\", \"-d\", domain, \"-l\", \"perms.txt\", \"-o\", \"resolved.txt\"]),\n        step.output(subs, path = path.file(\"resolved.txt\")),\n    ],\n)\n",[22,949,950,955,960,965,969,973,977,982,986,991,996,1001,1006,1010],{"__ignoreMap":37},[41,951,952],{"class":43,"line":44},[41,953,954],{},"# module: yourname\u002Fsubdomain-enum  — subfinder + permutation + validation\n",[41,956,957],{"class":43,"line":50},[41,958,959],{},"domain = input.string(name = \"domain\", description = \"Root domain\")\n",[41,961,962],{"class":43,"line":56},[41,963,964],{},"subs = output.file(name = \"subs\", description = \"Validated subdomains\")\n",[41,966,967],{"class":43,"line":62},[41,968,66],{"emptyLinePlaceholder":65},[41,970,971],{"class":43,"line":69},[41,972,72],{},[41,974,975],{"class":43,"line":75},[41,976,78],{},[41,978,979],{"class":43,"line":81},[41,980,981],{},"    outputs = [subs],\n",[41,983,984],{"class":43,"line":87},[41,985,90],{},[41,987,988],{"class":43,"line":93},[41,989,990],{},"        step.exec(command = [\"subfinder\", \"-d\", domain, \"-silent\", \"-o\", \"passive.txt\"]),\n",[41,992,993],{"class":43,"line":99},[41,994,995],{},"        step.exec(command = [\"alterx\", \"-l\", \"passive.txt\", \"-o\", \"perms.txt\"]),\n",[41,997,998],{"class":43,"line":105},[41,999,1000],{},"        step.exec(command = [\"shuffledns\", \"-d\", domain, \"-l\", \"perms.txt\", \"-o\", \"resolved.txt\"]),\n",[41,1002,1003],{"class":43,"line":111},[41,1004,1005],{},"        step.output(subs, path = path.file(\"resolved.txt\")),\n",[41,1007,1008],{"class":43,"line":117},[41,1009,138],{},[41,1011,1012],{"class":43,"line":123},[41,1013,144],{},[32,1015,1017],{"className":34,"code":1016,"language":36,"meta":37,"style":37},"# module: yourname\u002Fvuln-scan  — nuclei with curated templates\ntargets = input.file(name = \"targets\", description = \"Newline-delimited target URLs\")\nfindings = output.file(name = \"findings\", description = \"nuclei findings\")\n\nmodule(\n    inputs = [targets],\n    outputs = [findings],\n    steps = [\n        step.exec(command = [\"nuclei\", \"-l\", targets, \"-t\", \"templates\u002F\", \"-o\", \"findings.txt\"]),\n        step.output(findings, path = path.file(\"findings.txt\")),\n    ],\n)\n",[22,1018,1019,1024,1029,1034,1038,1042,1047,1052,1056,1061,1066,1070],{"__ignoreMap":37},[41,1020,1021],{"class":43,"line":44},[41,1022,1023],{},"# module: yourname\u002Fvuln-scan  — nuclei with curated templates\n",[41,1025,1026],{"class":43,"line":50},[41,1027,1028],{},"targets = input.file(name = \"targets\", description = \"Newline-delimited target URLs\")\n",[41,1030,1031],{"class":43,"line":56},[41,1032,1033],{},"findings = output.file(name = \"findings\", description = \"nuclei findings\")\n",[41,1035,1036],{"class":43,"line":62},[41,1037,66],{"emptyLinePlaceholder":65},[41,1039,1040],{"class":43,"line":69},[41,1041,72],{},[41,1043,1044],{"class":43,"line":75},[41,1045,1046],{},"    inputs = [targets],\n",[41,1048,1049],{"class":43,"line":81},[41,1050,1051],{},"    outputs = [findings],\n",[41,1053,1054],{"class":43,"line":87},[41,1055,90],{},[41,1057,1058],{"class":43,"line":93},[41,1059,1060],{},"        step.exec(command = [\"nuclei\", \"-l\", targets, \"-t\", \"templates\u002F\", \"-o\", \"findings.txt\"]),\n",[41,1062,1063],{"class":43,"line":99},[41,1064,1065],{},"        step.output(findings, path = path.file(\"findings.txt\")),\n",[41,1067,1068],{"class":43,"line":105},[41,1069,138],{},[41,1071,1072],{"class":43,"line":111},[41,1073,144],{},[10,1075,1076,1077,1080],{},"And wire them into a workflow where each phase is one line. Module invocations\ncan be bound like any other value, and their outputs feed later steps directly\n— the reference to ",[22,1078,1079],{},"enum_run.outputs.subs"," is both the data flow and the\nordering:",[32,1082,1084],{"className":34,"code":1083,"language":36,"meta":37,"style":37},"load(\"yourname\u002Fsubdomain-enum\", \"subdomain_enum\")\nload(\"yourname\u002Fvuln-scan\", \"vuln_scan\")\n\nenum_run = step.module(subdomain_enum, inputs = {\"domain\": config.var(\"target_domain\")})\nscan_run = step.module(vuln_scan, inputs = {\"targets\": enum_run.outputs.subs})\n\nworkflow(\n    name = \"full-hunt\",\n    activities = [\n        activity(\n            name = \"hunt\",\n            triggers = [trigger.cron(\"0 0 * * *\")],\n            steps = [\n                enum_run,\n                scan_run,\n                step.upload_artifact(name = \"findings\", entries = [\n                    artifact_entry(\n                        source = scan_run.outputs.findings,\n                        destination = path.file(\"findings.txt\"),\n                    ),\n                ]),\n            ],\n        ),\n    ],\n)\n",[22,1085,1086,1091,1096,1100,1105,1110,1114,1119,1124,1129,1134,1139,1144,1149,1154,1159,1164,1169,1175,1181,1187,1193,1199,1204,1209],{"__ignoreMap":37},[41,1087,1088],{"class":43,"line":44},[41,1089,1090],{},"load(\"yourname\u002Fsubdomain-enum\", \"subdomain_enum\")\n",[41,1092,1093],{"class":43,"line":50},[41,1094,1095],{},"load(\"yourname\u002Fvuln-scan\", \"vuln_scan\")\n",[41,1097,1098],{"class":43,"line":56},[41,1099,66],{"emptyLinePlaceholder":65},[41,1101,1102],{"class":43,"line":62},[41,1103,1104],{},"enum_run = step.module(subdomain_enum, inputs = {\"domain\": config.var(\"target_domain\")})\n",[41,1106,1107],{"class":43,"line":69},[41,1108,1109],{},"scan_run = step.module(vuln_scan, inputs = {\"targets\": enum_run.outputs.subs})\n",[41,1111,1112],{"class":43,"line":75},[41,1113,66],{"emptyLinePlaceholder":65},[41,1115,1116],{"class":43,"line":81},[41,1117,1118],{},"workflow(\n",[41,1120,1121],{"class":43,"line":87},[41,1122,1123],{},"    name = \"full-hunt\",\n",[41,1125,1126],{"class":43,"line":93},[41,1127,1128],{},"    activities = [\n",[41,1130,1131],{"class":43,"line":99},[41,1132,1133],{},"        activity(\n",[41,1135,1136],{"class":43,"line":105},[41,1137,1138],{},"            name = \"hunt\",\n",[41,1140,1141],{"class":43,"line":111},[41,1142,1143],{},"            triggers = [trigger.cron(\"0 0 * * *\")],\n",[41,1145,1146],{"class":43,"line":117},[41,1147,1148],{},"            steps = [\n",[41,1150,1151],{"class":43,"line":123},[41,1152,1153],{},"                enum_run,\n",[41,1155,1156],{"class":43,"line":129},[41,1157,1158],{},"                scan_run,\n",[41,1160,1161],{"class":43,"line":135},[41,1162,1163],{},"                step.upload_artifact(name = \"findings\", entries = [\n",[41,1165,1166],{"class":43,"line":141},[41,1167,1168],{},"                    artifact_entry(\n",[41,1170,1172],{"class":43,"line":1171},18,[41,1173,1174],{},"                        source = scan_run.outputs.findings,\n",[41,1176,1178],{"class":43,"line":1177},19,[41,1179,1180],{},"                        destination = path.file(\"findings.txt\"),\n",[41,1182,1184],{"class":43,"line":1183},20,[41,1185,1186],{},"                    ),\n",[41,1188,1190],{"class":43,"line":1189},21,[41,1191,1192],{},"                ]),\n",[41,1194,1196],{"class":43,"line":1195},22,[41,1197,1198],{},"            ],\n",[41,1200,1202],{"class":43,"line":1201},23,[41,1203,126],{},[41,1205,1207],{"class":43,"line":1206},24,[41,1208,138],{},[41,1210,1212],{"class":43,"line":1211},25,[41,1213,144],{},[14,1215,1217],{"id":1216},"contract-rules-recap","Contract Rules Recap",[149,1219,1220,1223,1229],{},[152,1221,1222],{},"Inputs and outputs are lists of declaration refs; duplicate names are\nrejected.",[152,1224,1225,1226,521],{},"Every declared output must be assigned exactly once via ",[22,1227,1228],{},"step.output",[152,1230,1231],{},"The workflow stores references only — the module's steps run as part of the\ninvoking activity's execution.",[14,1233,1235],{"id":1234},"compilation-modes","Compilation Modes",[10,1237,1238,1239,1242,1243,276,1246,1249,1250,1252,1253,1256,1257,1260,1261,1263,1264,1266,1267,916,1270,1273,1274,1277,1278,1256,1280,1282,1283,1285,1286,1256,1289,1292,1293,1296],{},"Workflow files and module files compile in different modes. A workflow file\nproduces a ",[22,1240,1241],{},"workflow(...)"," value and has ",[22,1244,1245],{},"workflow",[22,1247,1248],{},"activity"," globals; a\nmodule file produces a ",[22,1251,24],{}," value and instead has ",[22,1254,1255],{},"input.*"," \u002F\n",[22,1258,1259],{},"output.*"," declaration namespaces. Inside a module, ",[22,1262,1245],{}," and ",[22,1265,1248],{},"\nare unavailable, as are the project-context namespaces ",[22,1268,1269],{},"config",[22,1271,1272],{},"dataset",",\nand ",[22,1275,1276],{},"mcp",": a module must stay pure and receive configuration and data through\nits declared inputs, so callers bind values like ",[22,1279,275],{},[22,1281,279],{}," at the ",[22,1284,420],{}," call site. Agent steps remain\navailable.\nInside a workflow, bare ",[22,1287,1288],{},"input.string(name = ...)",[22,1290,1291],{},"output.file(name = ...)"," declarations are unavailable (workflows use\n",[22,1294,1295],{},"trigger.dispatch(inputs = {...})"," for inputs).",[10,1298,1299,1300,1302,1303,521],{},"Omitted optional module inputs fall back to their declared ",[22,1301,227],{}," at\ninvocation time; a required input with no default must always be bound by\n",[22,1304,1305],{},"step.module(..., inputs = {...})",[14,1307,1309],{"id":1308},"how-modules-work","How Modules Work",[10,1311,1312,1313,1316],{},"A module is a ",[22,1314,1315],{},"Module { inputs, outputs, steps }"," value. It is not an\nactivity and not a scheduling boundary — its steps run as part of the\ninvoking activity's execution.",[149,1318,1319,1356,1387,1399,1441,1465],{},[152,1320,1321,1324,1325,1328,1329,276,1331,1333,1334,916,1336,916,1338,1340,1341,1344,1345,276,1348,276,1350,1352,1353,1355],{},[27,1322,1323],{},"Compilation modes are explicit and never inferred."," A workflow file is\ncompiled in ",[22,1326,1327],{},"Workflow"," mode (",[22,1330,1245],{},[22,1332,1248],{}," globals plus\n",[22,1335,1269],{},[22,1337,1276],{},[22,1339,1272],{},"); a module file is compiled in ",[22,1342,1343],{},"Module"," mode\n(",[22,1346,1347],{},"module",[22,1349,1255],{},[22,1351,1259],{}," globals, dataset access disabled).\nA module file must contain exactly one top-level ",[22,1354,24],{},"\ndefinition; nothing is executed at compile time.",[152,1357,1358,1364,1365,1368,1369,1371,1372,1375,1376,1379,1380,1383,1384,604],{},[27,1359,1360,1361,521],{},"Identity is ",[22,1362,1363],{},"\u003Cusername>\u002F\u003Cmodule-name>"," ",[22,1366,1367],{},"ModuleRef::parse"," requires\nexactly one ",[22,1370,563],{}," separating two non-empty names of alphanumerics, ",[22,1373,1374],{},"-",", or\n",[22,1377,1378],{},"_",". The published export symbol is the module name with dashes replaced\nby underscores (",[22,1381,1382],{},"word-count"," → ",[22,1385,1386],{},"word_count",[152,1388,1389,1394,1395,1398],{},[27,1390,1391,1393],{},[22,1392,426],{}," is a pure import."," It resolves against the module registry\n(in-memory ",[22,1396,1397],{},"ModuleRegistry"," in tooling\u002Ftests, server-side in production),\nchecks that the requested symbol is exported, and freezes the definition\nfor the evaluator. It never executes the module or schedules steps.",[152,1400,1401,1364,1404,1407,1408,1410,1411,920,1414,916,1417,924,1420,1422,1423,276,1426,1428,1429,1432,1433,1435,1436,1438,1439,521],{},[27,1402,1403],{},"Inputs are symbolic refs.",[22,1405,1406],{},"input.string \u002F bool \u002F file \u002F directory(name = ...)"," produce an ",[22,1409,160],{}," carrying the public name, type, ",[22,1412,1413],{},"required",[22,1415,1416],{},"description",[22,1418,1419],{},"secret",[22,1421,227],{},". The Starlark variable name is just\na handle. String inputs compose with ",[22,1424,1425],{},"+",[22,1427,364],{}," as lazy\nexpressions resolved at execution time; bool inputs bind as booleans\n(",[22,1430,1431],{},"\"flag=\" + flag"," is rejected — use a conditional). File and directory\ninputs cannot be used as raw ",[22,1434,592],{}," argv elements; format them into\nstrings. ",[22,1437,231],{}," is string-only and forbids ",[22,1440,227],{},[152,1442,1443,1446,1447,1449,1450,1453,1454,1457,1458,276,1461,1464],{},[27,1444,1445],{},"Outputs are symbolic refs."," Today only ",[22,1448,1291],{},"\nexists, producing an ",[22,1451,1452],{},"OutputRef",". Each declared output must be assigned\nexactly once via ",[22,1455,1456],{},"step.output(ref, path = path.file(...))","; duplicate\ndeclaration names are rejected. ",[22,1459,1460],{},"Artifact",[22,1462,1463],{},"Table"," output types map to\npath values at invocation.",[152,1466,1467,1470,1473,1474,1477],{},[27,1468,1469],{},"Invocation binds by public name.",[22,1471,1472],{},"step.module(loaded_symbol, inputs = {name: value})"," validates unknown\ninputs, required bindings, and value types at save time, and exposes\n",[22,1475,1476],{},"invocation.outputs.\u003Cname>"," — a symbolic resource reference that is both\ndata flow and scheduling order for later steps.",[14,1479,1481],{"id":1480},"publishing-and-reusing","Publishing and Reusing",[10,1483,1484],{},"Modules are published under a publisher name and versioned by the platform:",[149,1486,1487,1501,1511],{},[152,1488,1489,1490,1493,1494,1497,1498,521],{},"Author at ",[22,1491,1492],{},"\u002Fu\u002F\u003Cyou>\u002Fworkflow-modules\u002Fnew",", then publish. Your modules are\nlisted on your profile (",[22,1495,1496],{},"\u002Fu\u002F\u003Cyou>?tab=workflow-modules",") and addressable\nas ",[22,1499,1500],{},"load(\"\u003Cyou>\u002F\u003Cmodule-name>\", \"\u003Csymbol>\")",[152,1502,1503,1504,1507,1508,521],{},"Organizations publish under the org: ",[22,1505,1506],{},"\u002Fo\u002F\u003Corg>\u002Fworkflow-modules\u002F\u003Cname>",",\nloaded as ",[22,1509,1510],{},"load(\"\u003Corg>\u002F\u003Cmodule-name>\", \"\u003Csymbol>\")",[152,1512,1513,1514,1517,1518,1521],{},"Workflow ",[27,1515,1516],{},"templates"," (",[22,1519,1520],{},"\u002Fu\u002F\u003Cyou>\u002Fworkflow-templates\u002F",") are the sibling\nconcept: whole-workflow starting points rather than composable phases.\nPrefer a module when the phase is reused inside other workflows; prefer a\ntemplate when the whole hunt is the reusable unit.",[1523,1524,1525],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":37,"searchDepth":69,"depth":62,"links":1527},[1528,1529,1531,1532,1535,1536,1537,1538,1539],{"id":16,"depth":50,"text":17},{"id":412,"depth":50,"text":1530},"Invoking a Module: load + step.module",{"id":546,"depth":50,"text":547},{"id":631,"depth":50,"text":632,"children":1533},[1534],{"id":900,"depth":56,"text":901},{"id":940,"depth":50,"text":941},{"id":1216,"depth":50,"text":1217},{"id":1234,"depth":50,"text":1235},{"id":1308,"depth":50,"text":1309},{"id":1480,"depth":50,"text":1481},"Package reusable hunting phases into modules with explicit input\u002Foutput contracts, share them, and invoke them with step.module.","md",{},"\u002Fworkflows\u002Fmodules",null,{"title":5,"description":1540},{"loc":1543},"01.workflows\u002F08.modules","f8Wz_DMA80PRrMsfzlY1UNaUXPrm29S3tHLc1xzPA7c",[1550,1608,1624,1643,1678,1694,1706,1717,1728,1739,1763,1782,1802,1813,1824],{"title":1551,"path":1552,"stem":1553,"children":1554,"page":-1},"Workflows","\u002Fworkflows","01.workflows",[1555,1557,1561,1565,1569,1573,1577,1581,1585,1589,1590,1592,1596,1600,1604],{"title":1551,"path":1552,"stem":1556},"01.workflows\u002Findex",{"title":1558,"path":1559,"stem":1560},"Workflow Quick Reference","\u002Fworkflows\u002Fquick-reference","01.workflows\u002F00.quick-reference",{"title":1562,"path":1563,"stem":1564},"Workflows Overview","\u002Fworkflows\u002Foverview","01.workflows\u002F01.overview",{"title":1566,"path":1567,"stem":1568},"Workflow Syntax Reference","\u002Fworkflows\u002Fsyntax-reference","01.workflows\u002F02.syntax-reference",{"title":1570,"path":1571,"stem":1572},"Steps","\u002Fworkflows\u002Fsteps","01.workflows\u002F03.steps",{"title":1574,"path":1575,"stem":1576},"Step Outputs","\u002Fworkflows\u002Fstep-outputs","01.workflows\u002F04.step-outputs",{"title":1578,"path":1579,"stem":1580},"Concurrency","\u002Fworkflows\u002Fconcurrency","01.workflows\u002F05.concurrency",{"title":1582,"path":1583,"stem":1584},"Transforms","\u002Fworkflows\u002Ftransforms","01.workflows\u002F06.transforms",{"title":1586,"path":1587,"stem":1588},"For Each","\u002Fworkflows\u002Ffor-each","01.workflows\u002F07.for-each",{"title":5,"path":1543,"stem":1547},{"title":937,"path":936,"stem":1591},"01.workflows\u002F09.agents",{"title":1593,"path":1594,"stem":1595},"Decisions","\u002Fworkflows\u002Fdecisions","01.workflows\u002F10.decisions",{"title":1597,"path":1598,"stem":1599},"Configuration References","\u002Fworkflows\u002Fconfig","01.workflows\u002F11.config",{"title":1601,"path":1602,"stem":1603},"Comparison With Other Automation Systems","\u002Fworkflows\u002Fcomparison","01.workflows\u002F12.comparison",{"title":1605,"path":1606,"stem":1607},"Generate with AI","\u002Fworkflows\u002Fai-generation","01.workflows\u002F13.ai-generation",{"title":1609,"path":1610,"stem":1611,"children":1612,"page":-1},"Projects","\u002Fprojects","02.projects",[1613,1616,1620],{"title":1614,"path":1610,"stem":1615},"Projects & Runs","02.projects\u002Findex",{"title":1617,"path":1618,"stem":1619},"Projects Overview","\u002Fprojects\u002Foverview","02.projects\u002F1.overview",{"title":1621,"path":1622,"stem":1623},"Runs & Artifacts","\u002Fprojects\u002Fruns-artifacts","02.projects\u002F2.runs-artifacts",{"title":1625,"path":1626,"stem":1627,"children":1628,"page":-1},"Runners","\u002Frunners","03.runners",[1629,1631,1635,1639],{"title":1625,"path":1626,"stem":1630},"03.runners\u002Findex",{"title":1632,"path":1633,"stem":1634},"Runner Overview","\u002Frunners\u002Foverview","03.runners\u002F1.overview",{"title":1636,"path":1637,"stem":1638},"Getting Started with Runners","\u002Frunners\u002Fgetting-started","03.runners\u002F2.getting-started",{"title":1640,"path":1641,"stem":1642},"Custom Runner Images","\u002Frunners\u002Fcustom-image","03.runners\u002F3.custom-image",{"title":1644,"path":1645,"stem":1646,"children":1647,"page":-1},"Datasets","\u002Fdatasets","04.datasets",[1648,1650,1654,1658,1662,1666,1670,1674],{"title":1644,"path":1645,"stem":1649},"04.datasets\u002Findex",{"title":1651,"path":1652,"stem":1653},"Datasets Overview","\u002Fdatasets\u002Foverview","04.datasets\u002F1.overview",{"title":1655,"path":1656,"stem":1657},"Dataset Schemas and Identity","\u002Fdatasets\u002Fschema","04.datasets\u002F2.schema",{"title":1659,"path":1660,"stem":1661},"Pushing and Reading Dataset Rows","\u002Fdatasets\u002Fworkflows","04.datasets\u002F3.workflows",{"title":1663,"path":1664,"stem":1665},"Dataset SQL Reference","\u002Fdatasets\u002Fsql","04.datasets\u002F4.sql",{"title":1667,"path":1668,"stem":1669},"Dataset Structured Filters","\u002Fdatasets\u002Ffilters","04.datasets\u002F5.filters",{"title":1671,"path":1672,"stem":1673},"Dataset Saved Views","\u002Fdatasets\u002Fviews","04.datasets\u002F6.views",{"title":1675,"path":1676,"stem":1677},"Datasets API and CLI","\u002Fdatasets\u002Fapi-cli","04.datasets\u002F7.api-cli",{"title":1679,"path":1680,"stem":1681,"children":1682,"page":-1},"Agent","\u002Fagent","05.agent",[1683,1686,1690],{"title":1684,"path":1680,"stem":1685},"BH Agent","05.agent\u002Findex",{"title":1687,"path":1688,"stem":1689},"BH Agent Overview","\u002Fagent\u002Foverview","05.agent\u002F1.overview",{"title":1691,"path":1692,"stem":1693},"MCP servers","\u002Fagent\u002Fmcp-servers","05.agent\u002F2.mcp-servers",{"title":1695,"path":1696,"stem":1697,"children":1698,"page":-1},"Bhlast","\u002Fbhlast","06.bhlast",[1699,1702],{"title":1700,"path":1696,"stem":1701},"Bhlast Servers","06.bhlast\u002Findex",{"title":1703,"path":1704,"stem":1705},"Bhlast servers overview","\u002Fbhlast\u002Foverview","06.bhlast\u002F1.overview",{"title":1707,"path":1708,"stem":1709,"children":1710,"page":-1},"Notifications","\u002Fnotifications","07.notifications",[1711,1713],{"title":1707,"path":1708,"stem":1712},"07.notifications\u002Findex",{"title":1714,"path":1715,"stem":1716},"Notifications Overview","\u002Fnotifications\u002Foverview","07.notifications\u002F1.overview",{"title":1718,"path":1719,"stem":1720,"children":1721,"page":-1},"Blob Storage","\u002Fblob-storage","08.blob-storage",[1722,1724],{"title":1718,"path":1719,"stem":1723},"08.blob-storage\u002Findex",{"title":1725,"path":1726,"stem":1727},"Blob Storage Overview","\u002Fblob-storage\u002Foverview","08.blob-storage\u002F1.overview",{"title":1729,"path":1730,"stem":1731,"children":1732,"page":-1},"Payloads","\u002Fpayloads","09.payloads",[1733,1735],{"title":1729,"path":1730,"stem":1734},"09.payloads\u002Findex",{"title":1736,"path":1737,"stem":1738},"Payloads overview","\u002Fpayloads\u002Foverview","09.payloads\u002F1.overview",{"title":1740,"path":1741,"stem":1742,"children":1743,"page":-1},"Cve Watcher","\u002Fcve-watcher","10.cve-watcher",[1744,1747,1751,1755,1759],{"title":1745,"path":1741,"stem":1746},"CVE Watcher","10.cve-watcher\u002Findex",{"title":1748,"path":1749,"stem":1750},"CVE Watcher Overview","\u002Fcve-watcher\u002Foverview","10.cve-watcher\u002F1.overview",{"title":1752,"path":1753,"stem":1754},"CVE Watcher Search and Filters","\u002Fcve-watcher\u002Fsearch","10.cve-watcher\u002F2.search",{"title":1756,"path":1757,"stem":1758},"CVE Watcher Push Notifications","\u002Fcve-watcher\u002Fnotifications","10.cve-watcher\u002F3.notifications",{"title":1760,"path":1761,"stem":1762},"CVE Watcher API and Scopes","\u002Fcve-watcher\u002Fapi","10.cve-watcher\u002F4.api",{"title":1764,"path":1765,"stem":1766,"children":1767,"page":-1},"Developer","\u002Fdeveloper","11.developer",[1768,1770,1774,1778],{"title":1764,"path":1765,"stem":1769},"11.developer\u002Findex",{"title":1771,"path":1772,"stem":1773},"Developer Overview","\u002Fdeveloper\u002Foverview","11.developer\u002F1.overview",{"title":1775,"path":1776,"stem":1777},"Personal Access Token Scopes","\u002Fdeveloper\u002Fscopes","11.developer\u002F2.scopes",{"title":1779,"path":1780,"stem":1781},"Personal Access Tokens","\u002Fdeveloper\u002Fpersonal-access-tokens","11.developer\u002F3.personal-access-tokens",{"title":1783,"path":1784,"stem":1785,"children":1786,"page":-1},"Bh","\u002Fbh","12.bh",[1787,1790,1794,1798],{"title":1788,"path":1784,"stem":1789},"BH CLI","12.bh\u002Findex",{"title":1791,"path":1792,"stem":1793},"BH CLI Overview","\u002Fbh\u002Foverview","12.bh\u002F1.overview",{"title":1795,"path":1796,"stem":1797},"BH CLI Commands","\u002Fbh\u002Fcommands","12.bh\u002F2.commands",{"title":1799,"path":1800,"stem":1801},"BH CLI Examples","\u002Fbh\u002Fexamples","12.bh\u002F3.examples",{"title":1803,"path":1804,"stem":1805,"children":1806,"page":-1},"Billing","\u002Fbilling","13.billing",[1807,1809],{"title":1803,"path":1804,"stem":1808},"13.billing\u002Findex",{"title":1810,"path":1811,"stem":1812},"Billing Overview","\u002Fbilling\u002Foverview","13.billing\u002F1.overview",{"title":1814,"path":1815,"stem":1816,"children":1817,"page":-1},"Tools","\u002Ftools","14.tools",[1818,1820],{"title":1814,"path":1815,"stem":1819},"14.tools\u002Findex",{"title":1821,"path":1822,"stem":1823},"Cookie Lab","\u002Ftools\u002Fcookie-lab","14.tools\u002F1.cookie-lab",{"title":1825,"path":1826,"stem":1827,"children":1828,"page":-1},"Site Policies","\u002Fsite-policies","99.site-policies",[1829,1831,1844,1848,1852,1856,1860,1864,1868],{"title":1825,"path":1826,"stem":1830},"99.site-policies\u002Findex",{"title":1832,"path":1833,"stem":1834,"children":1835},"Privacy Policy","\u002Fsite-policies\u002Fprivacy-policy","99.site-policies\u002F1.privacy-policy",[1836,1840],{"title":1837,"path":1838,"stem":1839},"Company Processors","\u002Fsite-policies\u002Fprivacy-policy\u002Fcompany-processors","99.site-policies\u002Fprivacy-policy\u002F1.company-processors",{"title":1841,"path":1842,"stem":1843},"Data Export Instructions","\u002Fsite-policies\u002Fprivacy-policy\u002Fdata-export-instructions","99.site-policies\u002Fprivacy-policy\u002F2.data-export-instructions",{"title":1845,"path":1846,"stem":1847},"Terms of Service","\u002Fsite-policies\u002Fterms-of-service","99.site-policies\u002F2.terms-of-service",{"title":1849,"path":1850,"stem":1851},"California Resident Notice at Collection","\u002Fsite-policies\u002Fccpa","99.site-policies\u002F3.ccpa",{"title":1853,"path":1854,"stem":1855},"Cancellation Policy","\u002Fsite-policies\u002Fcancellation-policy","99.site-policies\u002F4.cancellation-policy",{"title":1857,"path":1858,"stem":1859},"Refund Policy","\u002Fsite-policies\u002Frefund-policy","99.site-policies\u002F5.refund-policy",{"title":1861,"path":1862,"stem":1863},"Taxes on Services","\u002Fsite-policies\u002Ftaxes-on-services","99.site-policies\u002F6.taxes-on-services",{"title":1865,"path":1866,"stem":1867},"Disclaimer","\u002Fsite-policies\u002Fdisclaimer","99.site-policies\u002F7.disclaimer",{"title":1869,"path":1870,"stem":1871,"children":1872,"page":-1},"Security","\u002Fsite-policies\u002Fsecurity","99.site-policies\u002Fsecurity\u002Findex",[1873,1874,1878],{"title":1869,"path":1870,"stem":1871},{"title":1875,"path":1876,"stem":1877},"Security Overview","\u002Fsite-policies\u002Fsecurity\u002Fsecurity-overview","99.site-policies\u002Fsecurity\u002F1.security-overview",{"title":1879,"path":1880,"stem":1881},"Security Response","\u002Fsite-policies\u002Fsecurity\u002Fsecurity-response","99.site-policies\u002Fsecurity\u002F2.security-response",1794410311266]