chore: import upstream snapshot with attribution
This commit is contained in:
+383
@@ -0,0 +1,383 @@
|
||||
// Package ifc provides Information Flow Control labels for annotating MCP tool outputs.
|
||||
// The actual IFC enforcement engine lives in a separate service; this package only
|
||||
// defines the label schema used for annotations.
|
||||
package ifc
|
||||
|
||||
type Integrity string
|
||||
|
||||
const (
|
||||
IntegrityTrusted Integrity = "trusted"
|
||||
IntegrityUntrusted Integrity = "untrusted"
|
||||
)
|
||||
|
||||
type Confidentiality string
|
||||
|
||||
const (
|
||||
ConfidentialityPublic Confidentiality = "public"
|
||||
ConfidentialityPrivate Confidentiality = "private"
|
||||
)
|
||||
|
||||
type SecurityLabel struct {
|
||||
Integrity Integrity `json:"integrity"`
|
||||
Confidentiality Confidentiality `json:"confidentiality"`
|
||||
}
|
||||
|
||||
// PublicTrusted returns a label for trusted, publicly readable data.
|
||||
func PublicTrusted() SecurityLabel {
|
||||
return SecurityLabel{
|
||||
Integrity: IntegrityTrusted,
|
||||
Confidentiality: ConfidentialityPublic,
|
||||
}
|
||||
}
|
||||
|
||||
// PublicUntrusted returns a label for untrusted, publicly readable data.
|
||||
func PublicUntrusted() SecurityLabel {
|
||||
return SecurityLabel{
|
||||
Integrity: IntegrityUntrusted,
|
||||
Confidentiality: ConfidentialityPublic,
|
||||
}
|
||||
}
|
||||
|
||||
// PrivateTrusted returns a label for trusted data restricted to the readers
|
||||
// of the originating repository. The reader set is opaque on the wire (a
|
||||
// single "private" marker); the client engine resolves the concrete readers
|
||||
// from the GitHub API on demand at egress decision time.
|
||||
func PrivateTrusted() SecurityLabel {
|
||||
return SecurityLabel{
|
||||
Integrity: IntegrityTrusted,
|
||||
Confidentiality: ConfidentialityPrivate,
|
||||
}
|
||||
}
|
||||
|
||||
// PrivateUntrusted returns a label for untrusted data restricted to the
|
||||
// readers of the originating repository. See PrivateTrusted for the reader
|
||||
// resolution model.
|
||||
func PrivateUntrusted() SecurityLabel {
|
||||
return SecurityLabel{
|
||||
Integrity: IntegrityUntrusted,
|
||||
Confidentiality: ConfidentialityPrivate,
|
||||
}
|
||||
}
|
||||
|
||||
// LabelGetMe returns the IFC label for the authenticated user's own profile
|
||||
// (get_me).
|
||||
//
|
||||
// Integrity is trusted: this is GitHub-maintained data about the caller's own
|
||||
// account, not attacker-authored content.
|
||||
//
|
||||
// Confidentiality is private. The result includes fields that are NOT part of
|
||||
// the user's public profile — private_gists, total_private_repos, and
|
||||
// owned_private_repos — which are visible only to the authenticated user. The
|
||||
// result therefore must not be treated as world-readable.
|
||||
func LabelGetMe() SecurityLabel {
|
||||
return PrivateTrusted()
|
||||
}
|
||||
|
||||
// LabelListIssues returns the IFC label for a list_issues result.
|
||||
// Public repositories are universally readable; private repositories are
|
||||
// restricted to their collaborators (resolved client-side from the marker).
|
||||
// Public repository issue contents are attacker-controllable, while private
|
||||
// repository issues are treated as trusted collaborator-authored data.
|
||||
func LabelListIssues(isPrivate bool) SecurityLabel {
|
||||
if isPrivate {
|
||||
return PrivateTrusted()
|
||||
}
|
||||
return PublicUntrusted()
|
||||
}
|
||||
|
||||
// LabelRepoUserContent returns the IFC label for user-authored content scoped
|
||||
// to a repository when that tool has not opted into a more specific integrity
|
||||
// policy. Public repository content is untrusted because it may be authored by
|
||||
// outside contributors. Private repository content is trusted because users who
|
||||
// can read it are trusted collaborators.
|
||||
func LabelRepoUserContent(isPrivate bool) SecurityLabel {
|
||||
if isPrivate {
|
||||
return PrivateTrusted()
|
||||
}
|
||||
return PublicUntrusted()
|
||||
}
|
||||
|
||||
// LabelGetFileContents returns the IFC label for a get_file_contents result.
|
||||
// Public repository file contents may be authored by anyone via pull requests
|
||||
// and are therefore untrusted. In private repositories only collaborators can
|
||||
// land changes, so contents are treated as trusted.
|
||||
func LabelGetFileContents(isPrivate bool) SecurityLabel {
|
||||
if isPrivate {
|
||||
return PrivateTrusted()
|
||||
}
|
||||
return PublicUntrusted()
|
||||
}
|
||||
|
||||
// LabelSearchIssues returns the IFC label for a multi-repository search
|
||||
// result, joining per-repository labels across all matched repositories.
|
||||
// Used by both search_issues and search_repositories.
|
||||
//
|
||||
// Public-only results are untrusted and public. All-private results are trusted
|
||||
// and private because private repository content is treated as trusted
|
||||
// collaborator-authored data. Mixed public/private results are untrusted and
|
||||
// private: the public items keep the joined payload's integrity untrusted,
|
||||
// while the private items keep the joined payload's confidentiality private.
|
||||
// The reader set is opaque (the "private" marker); the client engine resolves
|
||||
// concrete readers on demand at egress decision time.
|
||||
//
|
||||
// An empty result set is treated as public-untrusted (no repository data is
|
||||
// leaked).
|
||||
//
|
||||
// Why a single joined label rather than one label per item: a tool result is
|
||||
// delivered as one opaque payload (a single content block) and the IFC engine
|
||||
// makes one allow/deny decision per flow at egress. Once the items share a
|
||||
// buffer in the agent's context they can be copied anywhere together, so the
|
||||
// only sound bound for the whole result is the meet of every item's label.
|
||||
// Per-item labels would only become load-bearing if the enforcement engine
|
||||
// could partition a result and route individual items to different sinks;
|
||||
// until then they would invite unsafe declassification of a "public" item that
|
||||
// actually arrived alongside private data.
|
||||
func LabelSearchIssues(repoVisibilities []bool) SecurityLabel {
|
||||
var anyPrivate, anyPublic bool
|
||||
for _, isPrivate := range repoVisibilities {
|
||||
if isPrivate {
|
||||
anyPrivate = true
|
||||
} else {
|
||||
anyPublic = true
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case anyPrivate && anyPublic:
|
||||
return PrivateUntrusted()
|
||||
case anyPrivate:
|
||||
return PrivateTrusted()
|
||||
default:
|
||||
return PublicUntrusted()
|
||||
}
|
||||
}
|
||||
|
||||
// LabelRepoMetadata returns the IFC label for structural repository metadata
|
||||
// that only collaborators with write access can define: labels, branches,
|
||||
// tags, releases, issue types, issue field definitions, discussion
|
||||
// categories, and the collaborator roster.
|
||||
//
|
||||
// Integrity is trusted because, unlike issue/PR/comment bodies, these
|
||||
// artifacts cannot be authored by arbitrary outsiders — creating a branch,
|
||||
// tag, release, or label requires push access, so the data reflects decisions
|
||||
// made by the repository's trusted writers rather than attacker-controllable
|
||||
// input.
|
||||
//
|
||||
// Confidentiality follows repository visibility: public repositories are
|
||||
// universally readable; private repositories restrict the reader set (the
|
||||
// opaque "private" marker, resolved client-side at egress time).
|
||||
func LabelRepoMetadata(isPrivate bool) SecurityLabel {
|
||||
if isPrivate {
|
||||
return PrivateTrusted()
|
||||
}
|
||||
return PublicTrusted()
|
||||
}
|
||||
|
||||
// LabelRelease returns the IFC label for repository releases (list_releases,
|
||||
// get_latest_release, get_release_by_tag).
|
||||
//
|
||||
// Integrity is trusted: releases are published by collaborators with push
|
||||
// access, not by arbitrary outsiders.
|
||||
//
|
||||
// Confidentiality is public only when the repository is public AND no returned
|
||||
// release is a draft. Draft releases are visible only to users with push
|
||||
// access — they are NOT world-readable even on a public repository — so a
|
||||
// result containing one must be private. hasDraft reflects whether any release
|
||||
// in the result is a draft; private repositories are always private regardless.
|
||||
func LabelRelease(isPrivate bool, hasDraft bool) SecurityLabel {
|
||||
if isPrivate || hasDraft {
|
||||
return PrivateTrusted()
|
||||
}
|
||||
return PublicTrusted()
|
||||
}
|
||||
|
||||
// LabelCollaboratorRoster returns the IFC label for a repository's collaborator
|
||||
// list (list_repository_collaborators).
|
||||
//
|
||||
// Integrity is trusted: the roster is GitHub-maintained membership data, not
|
||||
// attacker-authored content.
|
||||
//
|
||||
// Confidentiality is always private. Listing collaborators requires push
|
||||
// access to the repository, so the roster is never world-readable — not even
|
||||
// for public repositories. This mirrors LabelTeam: membership data is
|
||||
// restricted regardless of the repository's own visibility.
|
||||
func LabelCollaboratorRoster() SecurityLabel {
|
||||
return PrivateTrusted()
|
||||
}
|
||||
|
||||
// LabelCommitContents returns the IFC label for committed repository content
|
||||
// reachable from the default branch and its history: commits, commit diffs,
|
||||
// and the repository file tree.
|
||||
//
|
||||
// It shares the reasoning of LabelGetFileContents. In public repositories any
|
||||
// outsider can land content via a pull request, so the integrity of committed
|
||||
// content is untrusted. In private repositories only collaborators can push,
|
||||
// so committed content is trusted. Confidentiality follows repository
|
||||
// visibility.
|
||||
func LabelCommitContents(isPrivate bool) SecurityLabel {
|
||||
if isPrivate {
|
||||
return PrivateTrusted()
|
||||
}
|
||||
return PublicUntrusted()
|
||||
}
|
||||
|
||||
// LabelActionsResult returns the IFC label for GitHub Actions resources:
|
||||
// workflow definitions, runs, jobs, artifacts, and job logs.
|
||||
//
|
||||
// Integrity is untrusted. Workflow logs echo arbitrary text produced during a
|
||||
// run — including output derived from pull-request branches, dependency
|
||||
// downloads, and other attacker-influenceable sources — so log and artifact
|
||||
// content must be treated as low integrity. Workflow definitions are
|
||||
// themselves editable through pull requests in public repositories.
|
||||
//
|
||||
// Confidentiality follows repository visibility.
|
||||
func LabelActionsResult(isPrivate bool) SecurityLabel {
|
||||
if isPrivate {
|
||||
return PrivateUntrusted()
|
||||
}
|
||||
return PublicUntrusted()
|
||||
}
|
||||
|
||||
// LabelSecurityAlert returns the IFC label for security findings: code
|
||||
// scanning alerts, secret scanning alerts, and Dependabot alerts.
|
||||
//
|
||||
// Integrity is untrusted because alert payloads embed attacker-influenceable
|
||||
// material — the offending code snippet, the matched secret string, or a
|
||||
// vulnerable dependency's advisory text — none of which the agent should treat
|
||||
// as a trustworthy instruction source.
|
||||
//
|
||||
// Confidentiality is always private. Security alerts are access-restricted by
|
||||
// GitHub regardless of repository visibility (only users with a security role
|
||||
// can read them), so the reader set is narrow even for public repositories.
|
||||
// Secret scanning results additionally surface the secret material itself.
|
||||
func LabelSecurityAlert() SecurityLabel {
|
||||
return PrivateUntrusted()
|
||||
}
|
||||
|
||||
// LabelGlobalSecurityAdvisory returns the IFC label for advisories served from
|
||||
// the public GitHub Advisory Database (global advisories).
|
||||
//
|
||||
// The advisory database is world-readable, so confidentiality is public.
|
||||
// Integrity is untrusted: advisory descriptions are externally authored prose
|
||||
// and must not be treated as a trusted instruction source.
|
||||
func LabelGlobalSecurityAdvisory() SecurityLabel {
|
||||
return PublicUntrusted()
|
||||
}
|
||||
|
||||
// LabelRepositorySecurityAdvisory returns the IFC label for repository- or
|
||||
// organization-scoped security advisories.
|
||||
//
|
||||
// Integrity is untrusted (externally authored advisory prose).
|
||||
//
|
||||
// Confidentiality is public only when the repository is public AND every
|
||||
// advisory in the result is in the "published" state. Repository security
|
||||
// advisories also exist in draft, triage, and closed states; those are visible
|
||||
// only to maintainers and are NOT world-readable even on a public repository.
|
||||
// Treating any non-published advisory as private (allPublished == false)
|
||||
// prevents misclassifying an unpublished advisory from a public repo as
|
||||
// public-readable. Private repositories are always private regardless of state.
|
||||
func LabelRepositorySecurityAdvisory(isPrivate bool, allPublished bool) SecurityLabel {
|
||||
if isPrivate || !allPublished {
|
||||
return PrivateUntrusted()
|
||||
}
|
||||
return PublicUntrusted()
|
||||
}
|
||||
|
||||
// LabelGist returns the IFC label for gist content.
|
||||
//
|
||||
// Integrity is untrusted: gist contents are arbitrary user-authored text.
|
||||
// Confidentiality is public because secret gists are URL-accessible and cannot
|
||||
// be modeled as private to a GitHub reader set.
|
||||
func LabelGist() SecurityLabel {
|
||||
return PublicUntrusted()
|
||||
}
|
||||
|
||||
// LabelGistList returns the IFC label for a list of gists belonging to a user,
|
||||
// joining the per-gist confidentiality across the result set.
|
||||
//
|
||||
// Integrity is untrusted (user-authored content). Confidentiality is public
|
||||
// because even secret gists are URL-accessible.
|
||||
//
|
||||
// See LabelSearchIssues for why list results carry a single joined label
|
||||
// rather than one label per item.
|
||||
func LabelGistList() SecurityLabel {
|
||||
return PublicUntrusted()
|
||||
}
|
||||
|
||||
// LabelProject returns the IFC label for GitHub Project metadata (Projects v2),
|
||||
// such as get_project results and project field definitions.
|
||||
//
|
||||
// Public project metadata can contain public user-authored text, so it is
|
||||
// untrusted. Private project metadata is treated as trusted
|
||||
// collaborator-controlled data.
|
||||
//
|
||||
// Confidentiality derives from the project's own privacy — private projects
|
||||
// restrict the reader set, while public projects are universally readable.
|
||||
func LabelProject(isPrivate bool) SecurityLabel {
|
||||
if isPrivate {
|
||||
return PrivateTrusted()
|
||||
}
|
||||
return PublicUntrusted()
|
||||
}
|
||||
|
||||
// LabelProjectList returns the IFC label for a list_projects result, joining
|
||||
// the per-project labels across every returned project.
|
||||
//
|
||||
// Public-only results are untrusted and public. All-private results are trusted
|
||||
// and private. Mixed public/private results are untrusted and private: public
|
||||
// items keep the joined payload's integrity untrusted, while private items keep
|
||||
// the joined payload's confidentiality private.
|
||||
func LabelProjectList(projectVisibilities []bool) SecurityLabel {
|
||||
var anyPrivate, anyPublic bool
|
||||
for _, isPrivate := range projectVisibilities {
|
||||
if isPrivate {
|
||||
anyPrivate = true
|
||||
} else {
|
||||
anyPublic = true
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case anyPrivate && anyPublic:
|
||||
return PrivateUntrusted()
|
||||
case anyPrivate:
|
||||
return PrivateTrusted()
|
||||
default:
|
||||
return PublicUntrusted()
|
||||
}
|
||||
}
|
||||
|
||||
// LabelProjectContent returns the IFC label for project results that can include
|
||||
// item content, field values, or status update bodies. These can aggregate
|
||||
// content from a variety of sources, so integrity remains untrusted even when
|
||||
// the project is private.
|
||||
func LabelProjectContent(isPrivate bool) SecurityLabel {
|
||||
if isPrivate {
|
||||
return PrivateUntrusted()
|
||||
}
|
||||
return PublicUntrusted()
|
||||
}
|
||||
|
||||
// LabelTeam returns the IFC label for organization team membership data
|
||||
// (get_teams, get_team_members).
|
||||
//
|
||||
// Integrity is trusted: team membership is maintained by GitHub and cannot be
|
||||
// forged by outside contributors, so it is not an attacker-controllable
|
||||
// instruction source.
|
||||
//
|
||||
// Confidentiality is private. Organization team rosters and the teams a user
|
||||
// belongs to are visible only to members of the organization, not to the
|
||||
// public, so the reader set is restricted (the opaque "private" marker).
|
||||
func LabelTeam() SecurityLabel {
|
||||
return PrivateTrusted()
|
||||
}
|
||||
|
||||
// LabelNotificationDetails returns the IFC label for the subject of a single
|
||||
// notification.
|
||||
//
|
||||
// Integrity is untrusted: a notification subject points at an issue, pull
|
||||
// request, comment, or discussion whose content is user-authored and may carry
|
||||
// attacker-controlled text. Confidentiality is private because notifications
|
||||
// are delivered to a specific recipient and may reference private
|
||||
// repositories; the result cannot be assumed to be publicly readable.
|
||||
func LabelNotificationDetails() SecurityLabel {
|
||||
return PrivateUntrusted()
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
package ifc
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLabelListIssues(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("public repo issues are untrusted and public", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelListIssues(false)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("private repo issues are trusted and private", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelListIssues(true)
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelRepoUserContent(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("public repo user content is untrusted and public", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelRepoUserContent(false)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("private repo user content is trusted and private", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelRepoUserContent(true)
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelSearchIssues(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
visibilities []bool // true == private
|
||||
wantIntegrity Integrity
|
||||
wantConfidential Confidentiality
|
||||
}{
|
||||
{
|
||||
name: "empty result is treated as public",
|
||||
wantIntegrity: IntegrityUntrusted,
|
||||
wantConfidential: ConfidentialityPublic,
|
||||
},
|
||||
{
|
||||
name: "single public repo",
|
||||
visibilities: []bool{false},
|
||||
wantIntegrity: IntegrityUntrusted,
|
||||
wantConfidential: ConfidentialityPublic,
|
||||
},
|
||||
{
|
||||
name: "all public repos stay public",
|
||||
visibilities: []bool{false, false, false},
|
||||
wantIntegrity: IntegrityUntrusted,
|
||||
wantConfidential: ConfidentialityPublic,
|
||||
},
|
||||
{
|
||||
name: "mixed public and private repos become untrusted private",
|
||||
visibilities: []bool{false, true, false},
|
||||
wantIntegrity: IntegrityUntrusted,
|
||||
wantConfidential: ConfidentialityPrivate,
|
||||
},
|
||||
{
|
||||
name: "all private repos stay trusted private",
|
||||
visibilities: []bool{true, true},
|
||||
wantIntegrity: IntegrityTrusted,
|
||||
wantConfidential: ConfidentialityPrivate,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelSearchIssues(tc.visibilities)
|
||||
assert.Equal(t, tc.wantIntegrity, label.Integrity)
|
||||
assert.Equal(t, tc.wantConfidential, label.Confidentiality)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLabelRepoMetadata(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("public repo metadata is trusted and public", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelRepoMetadata(false)
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("private repo metadata is trusted and private", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelRepoMetadata(true)
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelGetMe(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// get_me exposes private_gists/total_private_repos/owned_private_repos,
|
||||
// which are not part of the public profile, so the result is trusted but
|
||||
// private — never public.
|
||||
label := LabelGetMe()
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
}
|
||||
|
||||
func TestLabelRelease(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("public repo with no draft is trusted and public", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelRelease(false, false)
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("public repo with a draft release is private", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Draft releases are visible only to push-access users, so a draft on
|
||||
// a public repo must not be labeled public.
|
||||
label := LabelRelease(false, true)
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("private repo is private regardless of draft", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, hasDraft := range []bool{false, true} {
|
||||
label := LabelRelease(true, hasDraft)
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelCollaboratorRoster(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// A collaborator roster requires push access to list, so it is never
|
||||
// world-readable — always trusted and private.
|
||||
label := LabelCollaboratorRoster()
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
}
|
||||
|
||||
func TestLabelCommitContents(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("public repo commit content is untrusted and public", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelCommitContents(false)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("private repo commit content is trusted and private", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelCommitContents(true)
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelActionsResult(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("public repo actions result is untrusted and public", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelActionsResult(false)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("private repo actions result is untrusted and private", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelActionsResult(true)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelSecurityAlert(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelSecurityAlert()
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality,
|
||||
"security alerts are access-restricted regardless of repo visibility")
|
||||
}
|
||||
|
||||
func TestLabelGlobalSecurityAdvisory(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelGlobalSecurityAdvisory()
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
}
|
||||
|
||||
func TestLabelRepositorySecurityAdvisory(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("public repo with all published advisories is untrusted and public", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelRepositorySecurityAdvisory(false, true)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("public repo with an unpublished advisory is untrusted and private", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// draft/triage/closed advisories are not world-readable even on a
|
||||
// public repo, so confidentiality must be private.
|
||||
label := LabelRepositorySecurityAdvisory(false, false)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("private repo advisory is untrusted and private", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelRepositorySecurityAdvisory(true, true)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("private repo with unpublished advisory is untrusted and private", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelRepositorySecurityAdvisory(true, false)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelGist(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("public gist is untrusted and public", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelGist()
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("secret gist is untrusted and public", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelGist()
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelGistList(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
label := LabelGistList()
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
}
|
||||
|
||||
func TestLabelProject(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("public project is untrusted and public", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelProject(false)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("private project metadata is trusted and private", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelProject(true)
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelProjectList(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
visibilities []bool // true == private
|
||||
wantIntegrity Integrity
|
||||
wantConfidential Confidentiality
|
||||
}{
|
||||
{
|
||||
name: "empty result is treated as public",
|
||||
wantIntegrity: IntegrityUntrusted,
|
||||
wantConfidential: ConfidentialityPublic,
|
||||
},
|
||||
{
|
||||
name: "all public projects stay public",
|
||||
visibilities: []bool{false, false},
|
||||
wantIntegrity: IntegrityUntrusted,
|
||||
wantConfidential: ConfidentialityPublic,
|
||||
},
|
||||
{
|
||||
name: "mixed public and private projects become untrusted private",
|
||||
visibilities: []bool{false, true},
|
||||
wantIntegrity: IntegrityUntrusted,
|
||||
wantConfidential: ConfidentialityPrivate,
|
||||
},
|
||||
{
|
||||
name: "all private projects stay trusted private",
|
||||
visibilities: []bool{true, true},
|
||||
wantIntegrity: IntegrityTrusted,
|
||||
wantConfidential: ConfidentialityPrivate,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelProjectList(tc.visibilities)
|
||||
assert.Equal(t, tc.wantIntegrity, label.Integrity)
|
||||
assert.Equal(t, tc.wantConfidential, label.Confidentiality)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLabelProjectContent(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("public project content is untrusted and public", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelProjectContent(false)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPublic, label.Confidentiality)
|
||||
})
|
||||
|
||||
t.Run("private project content is untrusted and private", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelProjectContent(true)
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelTeam(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelTeam()
|
||||
assert.Equal(t, IntegrityTrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
}
|
||||
|
||||
func TestLabelNotificationDetails(t *testing.T) {
|
||||
t.Parallel()
|
||||
label := LabelNotificationDetails()
|
||||
assert.Equal(t, IntegrityUntrusted, label.Integrity)
|
||||
assert.Equal(t, ConfidentialityPrivate, label.Confidentiality)
|
||||
}
|
||||
Reference in New Issue
Block a user