OpenAI + Google Drive, shareable code scan reports
You run a quick code scan, spot something worrying, then lose another hour turning messy notes into something you can actually send. The switching is the worst part. Tabs, screenshots, copy-paste, “where did that snippet come from?”
This kind of OpenAI Drive reports setup hits security consultants first, honestly. But in-house engineering leads and bug bounty hunters feel the same drag when they need clean evidence and a clear severity call.
This workflow runs static scans for JavaScript, PHP, or Python, then saves a client-ready HTML report to Google Drive. You’ll see what it automates, what you get out of it, and how to make it fit your own pipeline.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: OpenAI + Google Drive, shareable code scan reports
flowchart LR
subgraph sg0["Form Flow"]
direction LR
n0["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/form.svg' width='40' height='40' /></div><br/>Form"]
n1@{ icon: "mdi:robot", form: "rounded", label: "JavaScript Expert Agent (Sin..", pos: "b", h: 48 }
n2@{ icon: "mdi:brain", form: "rounded", label: "OpenAI JavaScript (Single URL)", pos: "b", h: 48 }
n3@{ icon: "mdi:web", form: "rounded", label: "HTTP Request JavaScript (Sin..", pos: "b", h: 48 }
n4["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Prettify JavaScript Results .."]
n5@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split JavaScript Expert Resu..", pos: "b", h: 48 }
n6@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Remove JavaScript Empty Resu..", pos: "b", h: 48 }
n7["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/html.dark.svg' width='40' height='40' /></div><br/>Create HTML Table JavaScript.."]
n8["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/html.dark.svg' width='40' height='40' /></div><br/>Create HTML Template JavaScr.."]
n9@{ icon: "mdi:robot", form: "rounded", label: "PHP Expert Agent (Single URL)", pos: "b", h: 48 }
n10@{ icon: "mdi:brain", form: "rounded", label: "OpenAI PHP (Single URL)", pos: "b", h: 48 }
n11@{ icon: "mdi:web", form: "rounded", label: "HTTP Request PHP (Single URL)", pos: "b", h: 48 }
n12["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Prettify PHP Results (Single.."]
n13@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split PHP Expert Results (Si..", pos: "b", h: 48 }
n14@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Remove PHP Empty Results (Si..", pos: "b", h: 48 }
n15["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/html.dark.svg' width='40' height='40' /></div><br/>Create HTML Table PHP (Singl.."]
n16["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/html.dark.svg' width='40' height='40' /></div><br/>Create HTML Template PHP (Si.."]
n17@{ icon: "mdi:robot", form: "rounded", label: "Python Expert Agent (Single ..", pos: "b", h: 48 }
n18@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Python (Single URL)", pos: "b", h: 48 }
n19@{ icon: "mdi:web", form: "rounded", label: "HTTP Request Python (Single ..", pos: "b", h: 48 }
n20["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Prettify Python Results (Sin.."]
n21@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Python Expert Results ..", pos: "b", h: 48 }
n22@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Remove Python Empty Results ..", pos: "b", h: 48 }
n23["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/html.dark.svg' width='40' height='40' /></div><br/>Create HTML Table Python (Si.."]
n24["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/html.dark.svg' width='40' height='40' /></div><br/>Create HTML Template Python .."]
n25@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split AI-Powered Code Analyz..", pos: "b", h: 48 }
n26@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Python Expert (Single URL)", pos: "b", h: 48 }
n27@{ icon: "mdi:swap-horizontal", form: "rounded", label: "PHP Expert (Single URL)", pos: "b", h: 48 }
n28@{ icon: "mdi:swap-horizontal", form: "rounded", label: "JavaScript Expert (Single URL)", pos: "b", h: 48 }
n29@{ icon: "mdi:cog", form: "rounded", label: "Upload HTML JavaScript Repor..", pos: "b", h: 48 }
n30@{ icon: "mdi:cog", form: "rounded", label: "Upload HTML PHP Report (Sing..", pos: "b", h: 48 }
n31@{ icon: "mdi:cog", form: "rounded", label: "Upload HTML Python Report (S..", pos: "b", h: 48 }
n0 --> n25
n10 -.-> n9
n27 --> n9
n18 -.-> n17
n26 --> n17
n11 -.-> n9
n9 --> n12
n28 --> n1
n2 -.-> n1
n19 -.-> n17
n17 --> n20
n12 --> n13
n15 --> n16
n3 -.-> n1
n1 --> n4
n20 --> n21
n23 --> n24
n16 --> n30
n14 --> n15
n13 --> n14
n24 --> n31
n4 --> n5
n22 --> n23
n21 --> n22
n7 --> n8
n25 --> n26
n25 --> n27
n25 --> n28
n8 --> n29
n6 --> n7
n5 --> n6
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n0 trigger
class n1,n9,n17 ai
class n2,n10,n18 aiModel
class n6,n14,n22,n26,n27,n28 decision
class n3,n11,n19 api
class n4,n12,n20 code
classDef customIcon fill:none,stroke:none
class n0,n4,n7,n8,n12,n15,n16,n20,n23,n24 customIcon
The Problem: Code scan results are hard to ship
Static analysis is supposed to be the “quick pass.” In reality, the scan is only half the job. The other half is turning raw findings into something structured, credible, and shareable. You end up reformatting output, hunting for the exact line numbers again, and rewriting the same severity explanations in slightly different words. One small mistake (wrong file URL, missing snippet, vague severity) and your report gets questioned, which means more back-and-forth and less time finding real issues.
The friction compounds. Here’s where it breaks down in day-to-day work.
- Findings get scattered across tools, so the “final report” becomes a manual assembly project.
- You spend about 1–2 hours per target just cleaning output and adding basic context.
- Small formatting inconsistencies make results look less trustworthy, even when the vulnerability is real.
- Sharing is awkward because raw logs don’t travel well, and screenshots don’t scale.
The Solution: AI-assisted static scans that publish clean HTML reports
This n8n workflow takes a code target, runs static security analysis with OpenAI-based agents, then produces a structured report you can send without apologizing for the formatting. It starts from a simple input form, where you choose the language analyzer (JavaScript, PHP, or Python) and provide the target details. For the selected language, the workflow fetches the relevant files (or URLs) using HTTP requests, then hands the content to a specialized AI “security agent” that looks for exploitable vulnerabilities using AST and regex-style heuristics. After that, it cleans and validates the returned JSON, builds a styled HTML table grouped by severity, and stores the finished HTML report in Google Drive.
The workflow begins with a form trigger, then routes you down the correct language branch. The agent produces strict JSON findings, n8n post-processes them, and Google Drive becomes your single place to grab the final client-ready report.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you review three small repos in a week (one JavaScript, one PHP, one Python). Manually, you might spend about 45 minutes per repo collecting snippets, rewriting into a table, and packaging it for sharing, so roughly 2–3 hours total. With this workflow, you submit each target in the form (a couple minutes), wait for analysis and HTML generation (often around 5–10 minutes), and then grab the finished report from Google Drive. That is usually a couple hours back per week, with reports that look consistent from the first run.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- OpenAI for AI-assisted vulnerability analysis
- Google Drive to store shareable HTML reports
- OpenAI API key (get it from your OpenAI dashboard)
Skill level: Intermediate. You’ll connect credentials, paste in keys, and verify a couple requests, but you won’t be writing a full app.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
You submit a target and pick a language analyzer. The workflow starts with an n8n form trigger. You choose JavaScript, PHP, or Python so the workflow routes your request to the right analysis branch.
Code is fetched from the source you provide. Each branch uses HTTP requests to pull file contents or URLs into the workflow. This keeps the evidence chain cleaner, because findings can reference the exact file path or URL they came from.
OpenAI agents generate exploitable findings in strict JSON. A language-specific security agent runs, backed by an OpenAI chat model tuned for that language. The response is constrained to a predictable JSON shape (URL, snippet, severity, vulnerability type), so it is usable downstream.
Results are cleaned, formatted, and published to Google Drive. n8n splits findings, drops empty items, then builds a styled HTML table and composes the final report. The last step stores that HTML file in Google Drive so you can share it with a link or attach it to a client email.
You can easily modify the severity rules to match your internal rubric based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Form Trigger
Set up the user input form that starts the workflow and collects the target file URL plus analyzer choice.
- Add and open Input Form Trigger.
- Set Form Title to
AI-Powered Code Analyzer. - Set Form Description to
Only one option can be selected from the three: (GitHub Repository, Domain To Crawl, Single File URL).. - In Form Fields, include a text field labeled
Single File URLwith placeholderhttps://example.com/path/file.js. - Add a checkbox field labeled
AI-Powered Code Analyzerwith optionsAI JavaScript Expert,AI PHP Expert, andAI Python Expert, and mark it as required.
AI-Powered Code Analyzer.Step 2: Split and Route the Analyzer Choice
Split the selected analyzer and route it to the correct language branch.
- Configure Split Analyzer Choice with Field To Split Out set to
["AI-Powered Code Analyzer"]. - In Route JS Choice, set the rule to compare Left Value
={{ $json["[\"AI-Powered Code Analyzer\"]"] }}with Right ValueAI JavaScript Expert. - In Route PHP Choice, set the rule to compare Left Value
={{ $json["[\"AI-Powered Code Analyzer\"]"] }}with Right ValueAI PHP Expert. - In Route Python Choice, set the rule to compare Left Value
={{ $json["[\"AI-Powered Code Analyzer\"]"] }}with Right ValueAI Python Expert.
Split Analyzer Choice outputs to both Route Python Choice, Route PHP Choice, and Route JS Choice in parallel.
Step 3: Set Up the AI Security Agents and Models
Each branch uses a language-specific model and agent; the HTTP fetch tools are attached to the agents.
- Open OpenAI JS Model and select model
gpt-4.1-mini. Credential Required: Connect youropenAiApicredentials. - Open OpenAI PHP Model and select model
gpt-4.1-mini. Credential Required: Connect youropenAiApicredentials. - Open OpenAI Python Model and select model
gpt-4.1-mini. Credential Required: Connect youropenAiApicredentials. - In JS Security Agent, set Text to
={{ $('Input Form Trigger').item.json['Single File URL'] }}and keep Prompt Type asdefine. Ensure OpenAI JS Model is connected as the language model for JS Security Agent. - In PHP Security Agent, set Text to
={{ $('Input Form Trigger').item.json['Single File URL'] }}and keep Prompt Type asdefine. Ensure OpenAI PHP Model is connected as the language model for PHP Security Agent. - In Python Security Agent, set Text to
={{ $('Input Form Trigger').item.json['Single File URL'] }}and keep Prompt Type asdefine. Ensure OpenAI Python Model is connected as the language model for Python Security Agent. - For each HTTP tool (JS File Fetch, PHP File Fetch, Python File Fetch), set URL to
={{ $('Input Form Trigger').item.json['Single File URL'] }}and keep Timeout at20000.
Step 4: Normalize and Filter the AI Results
Parse the model outputs into JSON, split findings, and remove empty results before report generation.
- In Format JS Results, keep the provided JavaScript Code as-is to normalize output JSON.
- In Format PHP Results and Format Python Results, keep the same parsing logic to handle string-wrapped JSON outputs.
- Configure Split JS Findings, Split PHP Findings, and Split Python Findings with Field To Split Out set to
results. - In Filter JS Blanks, Filter PHP Blanks, and Filter Python Blanks, ensure the condition checks Left Value
={{ $json.url }}with operatorexists.
Invalid JSON input.Step 5: Build HTML Reports
Convert findings to HTML tables and wrap them in a styled HTML template for each language branch.
- Set Build JS HTML Table, Build PHP HTML Table, and Build Python HTML Table to Operation
convertToHtmlTable. - In Compose JS HTML, Compose PHP HTML, and Compose Python HTML, keep the HTML template and ensure it injects the table using
{{ $json.table }}.
Step 6: Configure Google Drive Report Storage
Save each HTML report to Google Drive with a timestamped filename.
- Open Store JS HTML Report and set Operation to
createFromText, Content to={{ $json.html }}, and keep the dynamic Name expression=JavaScript Single URL {{ (() => {const d=new Date();return `${String(d.getDate()).padStart(2,'0')}-${String(d.getMonth()+1).padStart(2,'0')}-${d.getFullYear()} (${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')})`;})() }}.html. Credential Required: Connect yourgoogleDriveOAuth2Apicredentials. - Open Store PHP HTML Report and set Operation to
createFromText, Content to={{ $json.html }}, and keep the dynamic Name expression=PHP Single URL {{ (() => {const d=new Date();return `${String(d.getDate()).padStart(2,'0')}-${String(d.getMonth()+1).padStart(2,'0')}-${d.getFullYear()} (${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')})`;})() }}.html. Credential Required: Connect yourgoogleDriveOAuth2Apicredentials. - Open Store Python HTML Report and set Operation to
createFromText, Content to={{ $json.html }}, and keep the dynamic Name expression=Python Single URL {{ (() => {const d=new Date();return `${String(d.getDate()).padStart(2,'0')}-${String(d.getMonth()+1).padStart(2,'0')}-${d.getFullYear()} (${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')})`;})() }}.html. Credential Required: Connect yourgoogleDriveOAuth2Apicredentials.
My Drive and Folder is / (Root folder). Adjust if you want reports stored elsewhere.Step 7: Test and Activate Your Workflow
Validate each branch with real inputs, confirm report generation, and enable the workflow.
- Click Execute Workflow and submit the form in Input Form Trigger with a valid
Single File URLand one analyzer option. - Confirm the flow runs through the correct branch (JS, PHP, or Python) and that Format Results → Split Findings → Filter Blanks nodes produce items.
- Verify the HTML output is created in the corresponding Store JS HTML Report, Store PHP HTML Report, or Store Python HTML Report node and appears in Google Drive.
- If all outputs look correct, switch the workflow to Active so users can submit audits via the form.
Common Gotchas
- Google Drive credentials can expire or need specific permissions. If things break, check the connected Google account access and the n8n credential status first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Frequently Asked Questions
About 30 minutes if you already have your API keys ready.
No. You’ll mostly connect credentials and edit a couple fields. If you can follow a checklist, you’re fine.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in OpenAI API usage costs (often a few dollars a month for light scanning).
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, but you’ll swap the HTTP Request “file fetch” part to pull from GitHub’s API (or your repo source) before the JS/PHP/Python Security Agent runs. Common customizations include changing the input form fields, adding repo authentication, and adjusting the HTML template to match your client branding. If you keep the JSON schema the same, the formatting and Google Drive storage steps usually stay untouched.
Usually it’s an expired Google authorization or the connected account lost permission to write to the destination folder. Reconnect the Google Drive credential in n8n and confirm the folder location is still accessible. If you’re in a workspace, admin restrictions can also block file creation.
It depends on your n8n plan and how many files you feed it per run, but most small codebases are fine.
For this use case, n8n is usually the better fit because it can handle branching (JS vs PHP vs Python) and structured post-processing without turning into a fragile chain of zaps. Self-hosting also matters if you’re scanning often, since you’re not paying per task in the same way. Zapier and Make can work, but multi-step formatting (split, filter blanks, compose HTML, store) gets tedious fast. n8n’s AI Agent style flow is also easier to keep consistent once you’ve tuned prompts. Talk to an automation expert if you want help deciding.
Clean findings, consistent severity, and a Google Drive report you can share immediately. Set it up once, then stop rebuilding the same deliverable every time you scan.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.