Created
November 21, 2025 12:20
-
-
Save niedbalski/d39a419957c99b68b8801cb9024706e3 to your computer and use it in GitHub Desktop.
generate-app-comment.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Tool to trigger a GitHub PR comment by creating an event that generates an issue. | |
| // This simulates what happens when a GitHub Actions runner detects a security issue. | |
| package main | |
| import ( | |
| "context" | |
| "flag" | |
| "fmt" | |
| "log" | |
| "time" | |
| "github.com/garnet-org/jibril-ashkaal/pkg/kind" | |
| "github.com/garnet-org/jibril-ashkaal/pkg/ongoing" | |
| "github.com/google/uuid" | |
| "github.com/listendev/jibril-server/client" | |
| "github.com/listendev/jibril-server/types" | |
| ) | |
| func main() { | |
| var ( | |
| baseURL string | |
| projectToken string | |
| repo string | |
| prNumber string | |
| debug bool | |
| ) | |
| flag.StringVar(&baseURL, "url", "https://api.garnet.ai", "Garnet API URL") | |
| flag.StringVar(&projectToken, "token", "", "Project token (required)") | |
| flag.StringVar(&repo, "repo", "niedbalski/repeat", "GitHub repository (owner/repo)") | |
| flag.StringVar(&prNumber, "pr", "20", "Pull request number") | |
| flag.BoolVar(&debug, "debug", false, "Enable debug output") | |
| flag.Parse() | |
| if projectToken == "" { | |
| log.Fatal("--token is required") | |
| } | |
| ctx := context.Background() | |
| // Create client with project token | |
| c := client.New(baseURL, "").WithProjectToken(projectToken) | |
| c.Debug = debug | |
| // Step 0: Ensure the project setting for GitHub PR comments is enabled | |
| fmt.Println("Checking/creating project setting for GitHub PR comments...") | |
| _, err := c.ProjectSetting(ctx, "enabled_github_comment_pr") | |
| if err != nil { | |
| // Setting doesn't exist, try to create it | |
| fmt.Println("Setting not found, creating enabled_github_comment_pr=true...") | |
| setting := types.ProjectSettingCreate{ | |
| Key: "enabled_github_comment_pr", | |
| Value: []byte(`true`), | |
| } | |
| _, err = c.CreateProjectSetting(ctx, setting) | |
| if err != nil { | |
| log.Printf("Warning: Failed to create project setting: %v", err) | |
| log.Println("Make sure the setting 'enabled_github_comment_pr' is set to 'true' for this project") | |
| } else { | |
| fmt.Println("Project setting created successfully") | |
| } | |
| } else { | |
| fmt.Println("Project setting already exists") | |
| } | |
| // Step 1: Create a GitHub agent | |
| fmt.Println("Creating GitHub agent...") | |
| agentCreate := types.CreateAgent{ | |
| Kind: types.AgentKindGithub, | |
| Hostname: "github-runner-test", | |
| IP: "10.0.0.1", | |
| OS: "linux", | |
| Arch: "amd64", | |
| Version: "1.0.0", | |
| MachineID: uuid.New().String(), | |
| GithubContext: &types.AgentGithubContext{ | |
| Repository: repo, | |
| RepositoryOwner: "niedbalski", | |
| Workflow: "test-workflow.yml", | |
| Job: "test-job", | |
| RunID: "12345678", | |
| RunNumber: "1", | |
| RunAttempt: "1", | |
| Actor: "niedbalski", | |
| EventName: "pull_request", | |
| Ref: fmt.Sprintf("refs/pull/%s/merge", prNumber), | |
| RefName: fmt.Sprintf("pull/%s/merge", prNumber), | |
| SHA: "abc123def456", | |
| ServerURL: "https://github.com", | |
| }, | |
| } | |
| agentCreated, err := c.CreateAgent(ctx, agentCreate) | |
| if err != nil { | |
| log.Fatalf("Failed to create agent: %v", err) | |
| } | |
| fmt.Printf("Agent created: ID=%s, Token=%s\n", agentCreated.ID, agentCreated.AgentToken[:20]+"...") | |
| // Step 2: Switch to agent token for event ingestion | |
| agentClient := client.New(baseURL, "").WithAgentToken(agentCreated.AgentToken) | |
| agentClient.Debug = debug | |
| // Step 3: Create an event that will trigger an issue | |
| // Using a "dropdomain" detection which triggers the network_exfiltration issue class | |
| eventID := uuid.New().String() | |
| fmt.Printf("Creating event with ID: %s\n", eventID) | |
| now := time.Now() | |
| event := types.CreateOrUpdateEventV2{ | |
| ID: eventID, | |
| Kind: kind.KindDetections, | |
| CreatedAt: now, | |
| UpdatedAt: now, | |
| Data: ongoing.Base{ | |
| Metadata: &ongoing.Metadata{ | |
| Name: "dropdomain", // This triggers network_exfiltration issue | |
| }, | |
| Background: &ongoing.Background{ | |
| Flows: &ongoing.FlowAggregate{ | |
| IPVersion: 4, | |
| Protocols: []ongoing.ProtocolAggregate{ | |
| { | |
| Proto: "tcp", | |
| Pairs: []ongoing.ProtocolLocalRemoteAgg{ | |
| { | |
| Nodes: ongoing.LocalRemotePair{ | |
| Local: ongoing.ProtocolNode{ | |
| Address: "10.0.0.1", | |
| }, | |
| Remote: ongoing.ProtocolNode{ | |
| Address: "1.2.3.4", | |
| Name: "malicious.example.com", | |
| Names: []string{"malicious.example.com"}, | |
| }, | |
| }, | |
| PortMatrix: []ongoing.PortCommAgg{ | |
| { | |
| SrcPort: 54321, | |
| DstPort: 443, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| } | |
| result, err := agentClient.IngestEventV2(ctx, event) | |
| if err != nil { | |
| log.Fatalf("Failed to ingest event: %v", err) | |
| } | |
| fmt.Printf("Event ingested: ID=%s, Created=%v\n", result.ID, result.Created) | |
| fmt.Println("\n=== Summary ===") | |
| fmt.Printf("Repository: %s\n", repo) | |
| fmt.Printf("PR: #%s\n", prNumber) | |
| fmt.Printf("Agent ID: %s\n", agentCreated.ID) | |
| fmt.Printf("Event ID: %s\n", eventID) | |
| fmt.Println("\nIf everything is configured correctly:") | |
| fmt.Println("1. An issue should be created for this event") | |
| fmt.Println("2. A comment should be posted on the PR") | |
| fmt.Printf(" PR URL: https://github.com/%s/pull/%s\n", repo, prNumber) | |
| fmt.Println("\nMake sure the project has:") | |
| fmt.Println("- enabled_github_comment_pr setting set to 'true'") | |
| fmt.Println("- GitHub App configured with proper credentials") | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment