Fix: Smoke-Detector Workflow Vulnerability
Hey guys! Let's dive into fixing a pretty serious vulnerability in our smoke-detector workflow. This came up in Discussion #2950, and it's all about making sure our workflows are secure. So, buckle up, and let's get started!
Objective
The main goal here is to squash a HIGH severity dangerous-triggers vulnerability chilling in the smoke-detector.md workflow. The issue? We need to swap out the insecure workflow_run trigger for something way safer. This is crucial to protect our repository from potential bad actors.
Context
Okay, so here's the deal. The Zizmor security analysis (hat tip to Discussion #2950) pointed out that the workflow_run trigger can be a bit of a sneaky backdoor. It runs in the target repository's context, which means untrusted code from external forks could potentially get its hands on our precious repository secrets and credentials. That's a big no-no! It's like leaving the keys to the kingdom under the doormat.
Why is this a problem? Imagine someone creates a malicious fork of our repository. If we're using the workflow_run trigger without proper restrictions, their code could trigger our workflow and gain access to sensitive information like API keys, passwords, and other secrets. This could lead to all sorts of nasty stuff, from data breaches to unauthorized access to our systems.
Think of it this way: Our workflows are like automated robots that help us manage our projects. They can do things like run tests, deploy code, and send notifications. But if we don't secure them properly, they can be exploited by attackers. The workflow_run trigger, in its default configuration, is like giving anyone a remote control to our robots. We need to make sure that only authorized users can control them.
The key takeaway here is that security is paramount. We need to be proactive in identifying and mitigating potential vulnerabilities in our workflows. By replacing the insecure workflow_run trigger with a safer alternative, we can significantly reduce the risk of unauthorized access to our repository and its secrets.
Approach
We've got a few options to tackle this, ranked from the most awesome to still pretty good:
Option 1: Replace with workflow_call (Preferred)
This is the gold standard. Using workflow_call is like inviting specific workflows to the party, rather than letting anyone crash it.
on:
  workflow_call:
    inputs:
      source_workflow:
        description: 'Name of the calling workflow'
        required: false
        type: string
Why is this the preferred option?
- Granular Control: 
workflow_callallows us to explicitly define which workflows can trigger thesmoke-detectorworkflow. This means we can restrict access to trusted workflows only, preventing malicious code from external forks from gaining access. - Enhanced Security: By using 
workflow_call, we eliminate the risk of untrusted code running in the context of our repository. This significantly reduces the attack surface and makes it much harder for attackers to exploit our workflows. - Improved Maintainability: 
workflow_callmakes it easier to understand and manage the dependencies between workflows. We can clearly see which workflows are calling thesmoke-detectorworkflow, making it easier to track down and fix any issues. 
How does it work?
- We define the 
on: workflow_calltrigger in thesmoke-detectorworkflow. - We specify the inputs that the calling workflow needs to provide. In this case, we're asking for the name of the calling workflow.
 - The calling workflow uses the 
useskeyword to trigger thesmoke-detectorworkflow, passing in the required inputs. 
Example:
Let's say we have a workflow called build-and-test that we want to trigger the smoke-detector workflow. Here's how we would do it:
# In the build-and-test workflow
jobs:
  smoke-test:
    uses: ./.github/workflows/smoke-detector.yml
    with:
      source_workflow: build-and-test
This tells GitHub that we want to use the smoke-detector workflow and that the calling workflow is build-and-test.
Option 2: Add Branch Restrictions
If swapping to workflow_call isn't in the cards for some reason, we can at least put some guardrails on the workflow_run trigger.
on:
  workflow_run:
    types:
      - completed
    workflows:
      - "Some Workflow"
    branches:
      - main
Why is this a decent alternative?
- Reduced Risk: By restricting the 
workflow_runtrigger to specific workflows and branches, we can significantly reduce the risk of unauthorized access. We're essentially saying, "Only these workflows running on these branches can trigger this workflow." - Improved Security Posture: While not as secure as 
workflow_call, adding branch restrictions is a step in the right direction. It makes it harder for attackers to exploit theworkflow_runtrigger and gain access to our repository secrets. - Easier Implementation: Adding branch restrictions is relatively straightforward and can be done quickly. This makes it a good option if we need a quick fix to address the vulnerability.
 
How does it work?
- We define the 
on: workflow_runtrigger in thesmoke-detectorworkflow. - We specify the types of workflow run events that we want to trigger the workflow (e.g., 
completed). - We list the specific workflows that are allowed to trigger the workflow.
 - We specify the branches that the workflow must be running on to trigger the workflow.
 
Example:
Let's say we only want the build-and-deploy workflow running on the main branch to trigger the smoke-detector workflow. Here's how we would configure the workflow_run trigger:
on:
  workflow_run:
    types:
      - completed
    workflows:
      - build-and-deploy
    branches:
      - main
This tells GitHub that only the build-and-deploy workflow running on the main branch can trigger the smoke-detector workflow.
Option 3: Use pull_request Instead
If write permissions aren't a must-have, we can switch to using the pull_request trigger. This is like asking for permission before doing anything important.
on:
  pull_request:
    types: [opened, synchronize]
Why is this a less preferred option?
- Limited Functionality: The 
pull_requesttrigger only allows us to run workflows when a pull request is opened or synchronized. This means we can't use it to trigger workflows based on other events, such as workflow completion. - Reduced Automation: By switching to the 
pull_requesttrigger, we may need to manually trigger some workflows that were previously automated. This can increase our workload and slow down our development process. - Potential for False Positives: The 
pull_requesttrigger can sometimes generate false positives, especially if we have a lot of pull requests being opened and closed. This can lead to unnecessary workflow runs and wasted resources. 
How does it work?
- We define the 
on: pull_requesttrigger in thesmoke-detectorworkflow. - We specify the types of pull request events that we want to trigger the workflow (e.g., 
opened,synchronize). 
Example:
Let's say we want to run the smoke-detector workflow whenever a pull request is opened or synchronized. Here's how we would configure the pull_request trigger:
on:
  pull_request:
    types: [opened, synchronize]
This tells GitHub that we want to run the smoke-detector workflow whenever a pull request is opened or synchronized.
Files to Modify
Alright, time to get our hands dirty! We'll be tweaking these files:
.github/workflows/smoke-detector.md.github/workflows/smoke-detector.lock.yml(This one gets auto-generated, so don't sweat it too much)
Implementation Steps
Here's the game plan:
- Understand the Workflow: First, let's get cozy with the 
smoke-detectorworkflow. What's it doing? Why does it exist? - Pick the Best Fix: Based on what we've learned, let's choose the most suitable option from the ones above. Remember, 
workflow_callis the VIP choice. - Apply the Fix: Let's make the necessary changes to 
smoke-detector.md. - Recompile: Run 
gh aw compile smoke-detectorto regenerate that.lock.ymlfile. - Verify: Double-check our work with 
gh aw compile --zizmor. This will confirm that we've evicted that dangerous trigger. 
Acceptance Criteria
We'll know we've nailed it when:
- [ ] The 
workflow_runtrigger is either gone or properly locked down. - [ ] The workflow still does its job like a champ.
 - [ ] Zizmor gives us the all-clear – no more dangerous-triggers warning for 
smoke-detector. - [ ] The workflow recompiles without any hiccups.
 
Let's get this done and make our workflows rock-solid! This is related to issue #2950, so let's keep the conversation flowing there.