Skip to content

Commit fe4e2ba

Browse files
committed
add unit test to verify path based apps are not CSRF blocked
1 parent 658d7df commit fe4e2ba

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

coderd/coderd_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package coderd_test
33
import (
44
"context"
55
"flag"
6+
"fmt"
67
"io"
78
"net/http"
89
"net/netip"
@@ -21,6 +22,9 @@ import (
2122

2223
"cdr.dev/slog"
2324
"cdr.dev/slog/sloggers/slogtest"
25+
"github.com/coder/coder/v2/coderd/database"
26+
"github.com/coder/coder/v2/coderd/database/dbfake"
27+
"github.com/coder/coder/v2/provisionersdk/proto"
2428

2529
"github.com/coder/coder/v2/agent/agenttest"
2630
"github.com/coder/coder/v2/buildinfo"
@@ -315,3 +319,56 @@ func TestSwagger(t *testing.T) {
315319
require.Equal(t, "<pre>\n</pre>\n", string(body))
316320
})
317321
}
322+
323+
func TestCSRFExempt(t *testing.T) {
324+
t.Run("PathBasedApp", func(t *testing.T) {
325+
t.Parallel()
326+
327+
client, _, api := coderdtest.NewWithAPI(t, nil)
328+
first := coderdtest.CreateFirstUser(t, client)
329+
owner, err := client.User(context.Background(), "me")
330+
require.NoError(t, err)
331+
332+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
333+
defer cancel()
334+
335+
// Create a workspace.
336+
const agentSlug = "james"
337+
const appSlug = "web"
338+
wrk := dbfake.WorkspaceBuild(t, api.Database, database.Workspace{
339+
OwnerID: owner.ID,
340+
OrganizationID: first.OrganizationID,
341+
}).
342+
WithAgent(func(agents []*proto.Agent) []*proto.Agent {
343+
agents[0].Name = agentSlug
344+
agents[0].Apps = []*proto.App{{
345+
Slug: appSlug,
346+
DisplayName: appSlug,
347+
Subdomain: false,
348+
Url: "/",
349+
}}
350+
351+
return agents
352+
}).
353+
Do()
354+
355+
u := fmt.Sprintf(client.URL.JoinPath(fmt.Sprintf("/@%s/%s.%s/apps/%s", owner.Username, wrk.Workspace.Name, agentSlug, appSlug)).String())
356+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, nil)
357+
req.AddCookie(&http.Cookie{
358+
Name: codersdk.SessionTokenCookie,
359+
Value: client.SessionToken(),
360+
Path: "/",
361+
Domain: client.URL.String(),
362+
})
363+
require.NoError(t, err)
364+
365+
resp, err := client.HTTPClient.Do(req)
366+
require.NoError(t, err)
367+
data, _ := io.ReadAll(resp.Body)
368+
369+
// A StatusBadGateway means Coderd tried to proxy to the agent and failed because the agent
370+
// was not there. This means CSRF did not block the app request, which is what we want.
371+
require.Equal(t, http.StatusBadGateway, resp.StatusCode, "status code 500 is CSRF failure")
372+
require.NotContains(t, string(data), "CSRF")
373+
})
374+
}

0 commit comments

Comments
 (0)